Ich entwickle eine mehrschichtige Backend-API mit Controllern, Diensten, Repositorys usw.
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 }
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. } }
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),
)
}
// ...
Query
、QueryRow
、Exec
Kontext
..., etwa so: internal_server_error
rows, err := pgclient.GetSession().Query(ctx, query, param1, ...)
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) }
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), ) }
HandleContextCancel
scheint etwas überflüssig zu sein. Was denken Sie darüber? Unwrap() error
HandleContextCancel
nicht, Sie können einfach Folgendes tun: 🎜
if ctx.Err()!=nil { // Context timed out or canceled. Return return ctx.Err() }
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!