La fonctionnalité de tâche unique dans Asynq garantit qu'il n'y a qu'une seule tâche dans la file Redis.
Lorsque vous souhaitez éviter les tâches en double, cette fonctionnalité est très utile.
Aperçu
Il existe deux méthodes pour garantir l'unicité des tâches dans Asynq.
- Utilisation de l'option
TaskID
: Générez vous-même un identifiant de tâche unique. - Utilisation de l'option
Unique
: Laissez Asynq créer un verrou d'unicité pour la tâche.
Utilisation de l'option TaskID
Si vous choisissez la première méthode, vous pouvez garantir qu'il n'y a qu'une seule tâche avec un identifiant de tâche donné à tout moment. Si vous essayez de mettre en file une autre tâche avec le même identifiant de tâche, cela renverra une erreur ErrTaskIDConflict
.
// La première tâche devrait fonctionner
_, err := client.Enqueue(task, asynq.TaskID("monidentifiantdetâche"))
// La deuxième tâche échouera, l'erreur sera ErrTaskIDConflict (en supposant que la première tâche n'a pas encore été traitée)
_, err = client.Enqueue(task, asynq.TaskID("monidentifiantdetâche"))
Utilisation de l'option Unique
La deuxième méthode est basée sur le verrouillage d'unicité. Lors de la mise en file d'une tâche en utilisant l'option Unique
, le Client
vérifiera s'il peut acquérir le verrou pour la tâche donnée. La tâche ne sera mise en file que si le verrou peut être acquis. Si une autre tâche détient déjà le verrou, le Client
renverra une erreur (voir le code d'exemple ci-dessous sur la façon de vérifier les erreurs).
Le verrou d'unicité est associé à une durée de vie (TTL) pour éviter de le conserver indéfiniment. Le verrou sera libéré après le TTL ou après que la tâche a été traitée avec succès avant le TTL.
Il est important de noter que la fonctionnalité de tâche unique dans Asynq est une unicité à meilleur effort. En d'autres termes, si le verrou a expiré avant que la tâche ne soit traitée, une tâche en double peut être mise en file.
L'unicité de la tâche est basée sur les attributs suivants :
- Type
- Payload
- File d'attente
Par conséquent, s'il existe des tâches du même type et avec le même payload mises en file dans la même file d'attente, une autre tâche avec les mêmes attributs ne sera pas mise en file tant que le verrou n'aura pas été libéré.
c := asynq.NewClient(redis)
t1 := asynq.NewTask("exemple", []byte("bonjour"))
// t1 détiendra le verrou d'unicité pour la prochaine heure.
err := c.Enqueue(t1, asynq.Unique(time.Hour))
switch {
case errors.Is(err, asynq.ErrDuplicateTask):
// Gérer la tâche en double
case err != nil:
// Gérer les autres erreurs
}
t2 := asynq.NewTask("exemple", []byte("bonjour"))
// t2 ne peut pas être mis en file car c'est un doublon de t1.
err = c.Enqueue(t2, asynq.Unique(time.Hour))
switch {
case errors.Is(err, asynq.ErrDuplicateTask):
// Gérer la tâche en double
case err != nil:
// Gérer les autres erreurs
}
Dans l'exemple ci-dessus, t2
ne sera pas mis en file car c'est un doublon de t1
. Vous pouvez utiliser errors.Is
pour vérifier la valeur d'erreur retournée et déterminer si elle enveloppe l'erreur asynq.ErrDuplicateTask
.