Heim > Backend-Entwicklung > Golang > Umgang mit der schichtübergreifenden Kontextaufhebung

Umgang mit der schichtübergreifenden Kontextaufhebung

WBOY
Freigeben: 2024-02-05 23:54:07
nach vorne
489 Leute haben es durchsucht

Umgang mit der schichtübergreifenden Kontextaufhebung

Frageninhalt

Ich entwickle eine mehrschichtige Backend-API mit Controllern, Diensten, Repositorys usw.

Kontext

Jede Methode in diesen Ebenen verwendet context.Context als ersten Parameter, der den Anforderungskontext enthält. Dies ist praktisch, da jede Methode auf verschiedene anforderungsbezogene Daten zugreifen kann (z. B. Korrelations-ID usw.)

Jeder Anfragekontext hat eine Zeitüberschreitung, die von TimeoutMiddleware unten festgelegt wird:

func TimeoutMiddleware(timeoutFn func(*gin.Context) time.Duration) gin.HandlerFunc {
    return func(c *gin.Context) {
        timeout := timeoutFn(c)
        ctx, cancel := context.WithTimeout(c.Request.Context(), timeout)
        defer cancel()

        c.Request = c.Request.WithContext(ctx)

        c.Next()
    }
}

func TimeoutFn(c *gin.Context) time.Duration {
    return conf.HTTPRouter.DefaultContextTimeout
}
Nach dem Login kopieren

Herausforderung

Die Idee besteht darin, alle laufenden Vorgänge ordnungsgemäß zu stoppen, wenn der Anforderungskontext das Zeitlimit überschreitet. Basierend auf meinem (sehr geringen) Verständnis von Kontext und Parallelität habe ich diese Hilfsfunktion erstellt:

package helpers

import "context"

// Checks for context cancellation and returns ctx.Err() if canceled.
func HandleContextCancel(ctx context.Context) error {
    select {
    case <-ctx.Done(): // If the context is canceled
        return ctx.Err() // return immediately with the canceled error.

    default: 
        return nil // Continue with the normal processing.
    }
}

Nach dem Login kopieren

Theoretisch müsste ich, wenn ich jeden Vorgang so schnell wie möglich stoppen wollte, diese Funktion < /p> am Anfang

jeder Methode in der Anwendung aufrufen, etwa so:

func DoSomething(ctx context.Context, ...) resterrors.RestErr {
if err := helpers.HandleContextCancel(ctx); err != nil {
    return resterrors.NewRequestTimeoutError(
        fmt.Errorf("DoSomething: %w", err),
    )
}
// ...
Nach dem Login kopieren
Außerdem weiß ich, dass in dem Repository, das auf die Datenbank zugreift, die meisten Funktionen einen QueryQueryRowExecKontext

benötigen, wie zum Beispiel

..., etwa so: internal_server_error

rows, err := pgclient.GetSession().Query(ctx, query, param1, ...)
Nach dem Login kopieren

Also muss ich jedes Mal, wenn in der Zeile oben ein Fehler auftritt, prüfen, ob der Fehler nicht auf einen Kontextabbruch zurückzuführen ist, anstatt einfach

und eine Fehlermeldung wie diese zurückzugeben: HandleContextCancel 函数看起来有点多余,您对此有何看法?


正确答案


您不需要 HandleContextCancel

rows, err := pgclient.GetSession().Query(ctx, query, param1, ...)
if err != nil {
   return helpers.MapRepoError("DoSomething: Query Error:", err)
}
Nach dem Login kopieren
func MapRepoError(location string, err error) resterrors.RestErr {
    if errors.Is(err, context.DeadlineExceeded) {
        return resterrors.NewRequestTimeoutError(
            fmt.Errorf("%s request_timeout", location),
        )
    }
    return resterrors.NewInternalServerError(
        fmt.Errorf("%s %w", location, err),
    )
}
Nach dem Login kopieren

Die Verwendung der Funktion HandleContextCancel scheint etwas überflüssig zu sein. Was denken Sie darüber?

Unwrap() error

Richtige Antwort

🎜🎜Sie benötigen die Funktion HandleContextCancel nicht, Sie können einfach Folgendes tun: 🎜
if ctx.Err()!=nil {
  // Context timed out or canceled. Return
  return ctx.Err()
}
Nach dem Login kopieren
🎜Wenn Ihre anderen Fehlerbehandlungsfunktionen diesen Fehler korrekt umschließen (d. h. sie implementieren die 🎜-Methode), können Sie auf der obersten Ebene prüfen, ob der Fehler einen Timeout-/Abbruchfehler enthält, und entscheiden, welche Art von Fehler Sie zurückgeben möchten Sie müssen dies nicht für jedes Level tun 🎜.

Das obige ist der detaillierte Inhalt vonUmgang mit der schichtübergreifenden Kontextaufhebung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage