fix: Redis backend does not respect MaxRetries

This commit is contained in:
Adriano Caloiaro 2023-10-05 09:05:55 -06:00 committed by Adriano Caloiaro
parent c04ef692a7
commit 12a6667bd5
2 changed files with 98 additions and 13 deletions

View file

@ -218,18 +218,26 @@ func (b *RedisBackend) Start(_ context.Context, h handler.Handler) (err error) {
b.logger.Error("unable to process job", "error", err)
return
}
if !ti.Deadline.IsZero() && ti.Deadline.UTC().Before(time.Now().UTC()) {
err = jobs.ErrJobExceededDeadline
b.logger.Debug("job deadline is in the past, skipping", "task_id", taskID)
return
}
if ti.Retried >= ti.MaxRetry {
err = jobs.ErrJobExceededMaxRetries
b.logger.Debug("job has exceeded the maximum number of retries, skipping", "task_id", taskID)
return
}
job := &jobs.Job{
CreatedAt: time.Now().UTC(),
Queue: h.Queue,
Payload: p,
Deadline: &ti.Deadline,
RunAfter: ti.NextProcessAt,
CreatedAt: time.Now().UTC(),
Queue: h.Queue,
Payload: p,
Deadline: &ti.Deadline,
MaxRetries: &ti.MaxRetry,
RunAfter: ti.NextProcessAt,
}
ctx = withJobContext(ctx, job)
@ -288,6 +296,10 @@ func jobToTaskOptions(job *jobs.Job) (opts []asynq.Option) {
opts = append(opts, asynq.Deadline(*job.Deadline))
}
if job.MaxRetries != nil {
opts = append(opts, asynq.MaxRetry(*job.MaxRetries))
}
return
}

View file

@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
"log"
"os"
"testing"
"time"
@ -13,6 +12,7 @@ import (
"github.com/acaloiaro/neoq/handler"
"github.com/acaloiaro/neoq/internal"
"github.com/acaloiaro/neoq/jobs"
"github.com/acaloiaro/neoq/logging"
"github.com/acaloiaro/neoq/testutils"
"github.com/hibiken/asynq"
)
@ -22,6 +22,11 @@ const (
queue2 = "testing2"
)
var (
errTimeout = errors.New("the test has timed out")
asynqInspector *asynq.Inspector
)
func init() {
var err error
connString := os.Getenv("TEST_REDIS_URL")
@ -34,29 +39,29 @@ func init() {
if password != "" {
clientOpt.Password = password
}
inspector := asynq.NewInspector(clientOpt)
queues, err := inspector.Queues()
asynqInspector = asynq.NewInspector(clientOpt)
queues, err := asynqInspector.Queues()
if err != nil {
panic(err)
}
for _, queue := range queues {
_, err = inspector.DeleteAllPendingTasks(queue)
_, err = asynqInspector.DeleteAllPendingTasks(queue)
if err != nil {
panic(err)
}
_, err = inspector.DeleteAllCompletedTasks(queue)
_, err = asynqInspector.DeleteAllCompletedTasks(queue)
if err != nil {
panic(err)
}
_, err = inspector.DeleteAllRetryTasks(queue)
_, err = asynqInspector.DeleteAllRetryTasks(queue)
if err != nil {
panic(err)
}
_, err = inspector.DeleteAllArchivedTasks(queue)
_, err = asynqInspector.DeleteAllArchivedTasks(queue)
if err != nil {
panic(err)
}
@ -110,7 +115,6 @@ func TestBasicJobProcessing(t *testing.T) {
case <-timeoutTimer:
err = jobs.ErrJobTimeout
case <-done:
log.Println("DONE")
}
if err != nil {
@ -368,3 +372,72 @@ func TestJobProcessingWithJobDeadline(t *testing.T) {
t.Error(err)
}
}
func TestMaxRetries(t *testing.T) {
const queue = "foobar"
maxRetries := 0
ctx := context.Background()
connString := os.Getenv("TEST_REDIS_URL")
if connString == "" {
t.Skip("Skipping: TEST_REDIS_URL not set")
return
}
password := os.Getenv("REDIS_PASSWORD")
nq, err := neoq.New(
ctx,
neoq.WithBackend(Backend),
neoq.WithLogLevel(logging.LogLevelDebug),
WithAddr(connString),
WithPassword(password),
)
if err != nil {
t.Fatal(err)
}
defer nq.Shutdown(ctx)
h := handler.New(queue, func(ctx context.Context) (err error) {
panic("i refuse success!")
})
err = nq.Start(ctx, h)
if err != nil {
t.Error(err)
}
// allow time for listener to start
time.Sleep(5 * time.Millisecond)
var taskID string
taskID, err = nq.Enqueue(ctx, &jobs.Job{
Queue: queue,
Payload: map[string]any{
"message": fmt.Sprintf("hello world: %d", internal.RandInt(10000000000)),
},
MaxRetries: &maxRetries,
})
if err != nil {
t.Error(err)
}
timeoutTimer := time.After(5 * time.Second)
result_loop:
for {
select {
case <-timeoutTimer:
err = errTimeout
break result_loop
default:
ti, _ := asynqInspector.GetTaskInfo(defaultAsynqQueue, taskID)
if ti.State == asynq.TaskStateArchived && ti.Retried == maxRetries {
break result_loop
}
time.Sleep(50 * time.Millisecond)
}
}
if err != nil {
t.Error(err)
}
}