Maison > développement back-end > Golang > Gestion de l'annulation de contexte multicouche

Gestion de l'annulation de contexte multicouche

WBOY
Libérer: 2024-02-05 23:54:07
avant
525 Les gens l'ont consulté

Gestion de lannulation de contexte multicouche

Contenu de la question

Je développe une API backend en couches avec des contrôleurs, des services, des référentiels, etc.

Contexte

Chaque méthode de ces couches prend context.Context comme premier paramètre contenant le contexte de requête. C'est pratique car n'importe quelle méthode peut accéder à diverses données liées à la requête (telles que l'ID de corrélation, etc.)

Chaque contexte de requête a un délai d'attente défini par TimeoutMiddleware ci-dessous :

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
}
Copier après la connexion

Défi

L'idée est d'arrêter gracieusement toutes les opérations en cours lorsque le contexte de la demande expire. Sur la base de ma compréhension du contexte et de la concurrence (très peu), j'ai construit cette fonction d'assistance :

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.
    }
}

Copier après la connexion

Théoriquement, si je voulais arrêter toute opération dès que possible , j'aurais besoin d'appeler cette fonction < /p> au début

de chaque méthode de l'application, comme ceci :

func DoSomething(ctx context.Context, ...) resterrors.RestErr {
if err := helpers.HandleContextCancel(ctx); err != nil {
    return resterrors.NewRequestTimeoutError(
        fmt.Errorf("DoSomething: %w", err),
    )
}
// ...
Copier après la connexion
De plus, je sais que dans le référentiel qui accède à la base de données, la plupart des fonctions nécessitent un QueryQueryRowExeccontexte

, tel que

..., comme ceci : internal_server_error

rows, err := pgclient.GetSession().Query(ctx, query, param1, ...)
Copier après la connexion

Donc, chaque fois qu'une erreur se produit dans la ligne ci-dessus, je dois vérifier si l'erreur n'est pas due à une annulation de contexte au lieu de simplement renvoyer

et un message d'erreur comme celui-ci : HandleContextCancel 函数看起来有点多余,您对此有何看法?


正确答案


您不需要 HandleContextCancel

rows, err := pgclient.GetSession().Query(ctx, query, param1, ...)
if err != nil {
   return helpers.MapRepoError("DoSomething: Query Error:", err)
}
Copier après la connexion
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),
    )
}
Copier après la connexion

Utiliser la fonction HandleContextCancel semble un peu redondant, qu'en pensez-vous ?

Unwrap() error

Bonne réponse

🎜🎜Vous n'avez pas besoin de la fonction HandleContextCancel, vous pouvez simplement faire ce qui suit : 🎜
if ctx.Err()!=nil {
  // Context timed out or canceled. Return
  return ctx.Err()
}
Copier après la connexion
🎜Si vos autres fonctions de gestion des erreurs encapsulent correctement cette erreur (c'est-à-dire qu'elles implémentent la méthode 🎜), vous pouvez alors vérifier au niveau supérieur si l'erreur contient une erreur de délai d'attente/d'annulation et décider quel type d'erreur vous souhaitez que vous souhaitiez renvoyer. vous n'êtes pas obligé de faire cela pour tous les niveaux 🎜.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal