2
0
mirror of https://github.com/hibiken/asynq.git synced 2024-12-27 00:02:19 +08:00

Update ProcessorRetry test

This commit is contained in:
Ken Hibino 2021-06-03 06:33:21 -07:00
parent b0321fb465
commit f9d7af3def

View File

@ -44,6 +44,7 @@ func fakeSyncer(syncCh <-chan *syncRequest, done <-chan struct{}) {
func TestProcessorSuccessWithSingleQueue(t *testing.T) { func TestProcessorSuccessWithSingleQueue(t *testing.T) {
r := setup(t) r := setup(t)
defer r.Close()
rdbClient := rdb.NewRDB(r) rdbClient := rdb.NewRDB(r)
m1 := h.NewTaskMessage("task1", nil) m1 := h.NewTaskMessage("task1", nil)
@ -146,6 +147,7 @@ func TestProcessorSuccessWithMultipleQueues(t *testing.T) {
t3 = NewTask(m3.Type, m3.Payload) t3 = NewTask(m3.Type, m3.Payload)
t4 = NewTask(m4.Type, m4.Payload) t4 = NewTask(m4.Type, m4.Payload)
) )
defer r.Close()
tests := []struct { tests := []struct {
pending map[string][]*base.TaskMessage pending map[string][]*base.TaskMessage
@ -226,6 +228,7 @@ func TestProcessorSuccessWithMultipleQueues(t *testing.T) {
// https://github.com/hibiken/asynq/issues/166 // https://github.com/hibiken/asynq/issues/166
func TestProcessTasksWithLargeNumberInPayload(t *testing.T) { func TestProcessTasksWithLargeNumberInPayload(t *testing.T) {
r := setup(t) r := setup(t)
defer r.Close()
rdbClient := rdb.NewRDB(r) rdbClient := rdb.NewRDB(r)
m1 := h.NewTaskMessage("large_number", h.JSON(map[string]interface{}{"data": 111111111111111111})) m1 := h.NewTaskMessage("large_number", h.JSON(map[string]interface{}{"data": 111111111111111111}))
@ -302,6 +305,7 @@ func TestProcessTasksWithLargeNumberInPayload(t *testing.T) {
func TestProcessorRetry(t *testing.T) { func TestProcessorRetry(t *testing.T) {
r := setup(t) r := setup(t)
defer r.Close()
rdbClient := rdb.NewRDB(r) rdbClient := rdb.NewRDB(r)
m1 := h.NewTaskMessage("send_email", nil) m1 := h.NewTaskMessage("send_email", nil)
@ -312,66 +316,55 @@ func TestProcessorRetry(t *testing.T) {
errMsg := "something went wrong" errMsg := "something went wrong"
wrappedSkipRetry := fmt.Errorf("%s:%w", errMsg, SkipRetry) wrappedSkipRetry := fmt.Errorf("%s:%w", errMsg, SkipRetry)
now := time.Now()
tests := []struct { tests := []struct {
desc string // test description desc string // test description
pending []*base.TaskMessage // initial default queue state pending []*base.TaskMessage // initial default queue state
incoming []*base.TaskMessage // tasks to be enqueued during run
delay time.Duration // retry delay duration delay time.Duration // retry delay duration
handler Handler // task handler handler Handler // task handler
wait time.Duration // wait duration between starting and stopping processor for this test case wait time.Duration // wait duration between starting and stopping processor for this test case
wantRetry []base.Z // tasks in retry queue at the end wantErrMsg string // error message the task should record
wantRetry []*base.TaskMessage // tasks in retry queue at the end
wantArchived []*base.TaskMessage // tasks in archived queue at the end wantArchived []*base.TaskMessage // tasks in archived queue at the end
wantErrCount int // number of times error handler should be called wantErrCount int // number of times error handler should be called
}{ }{
{ {
desc: "Should automatically retry errored tasks", desc: "Should automatically retry errored tasks",
pending: []*base.TaskMessage{m1, m2}, pending: []*base.TaskMessage{m1, m2, m3, m4},
incoming: []*base.TaskMessage{m3, m4}, delay: time.Minute,
delay: time.Minute,
handler: HandlerFunc(func(ctx context.Context, task *Task) error { handler: HandlerFunc(func(ctx context.Context, task *Task) error {
return fmt.Errorf(errMsg) return fmt.Errorf(errMsg)
}), }),
wait: 2 * time.Second, wait: 2 * time.Second,
wantRetry: []base.Z{ wantErrMsg: errMsg,
{Message: h.TaskMessageAfterRetry(*m2, errMsg), Score: now.Add(time.Minute).Unix()}, wantRetry: []*base.TaskMessage{m2, m3, m4},
{Message: h.TaskMessageAfterRetry(*m3, errMsg), Score: now.Add(time.Minute).Unix()}, wantArchived: []*base.TaskMessage{m1},
{Message: h.TaskMessageAfterRetry(*m4, errMsg), Score: now.Add(time.Minute).Unix()},
},
wantArchived: []*base.TaskMessage{h.TaskMessageWithError(*m1, errMsg)},
wantErrCount: 4, wantErrCount: 4,
}, },
{ {
desc: "Should skip retry errored tasks", desc: "Should skip retry errored tasks",
pending: []*base.TaskMessage{m1, m2}, pending: []*base.TaskMessage{m1, m2},
incoming: []*base.TaskMessage{}, delay: time.Minute,
delay: time.Minute,
handler: HandlerFunc(func(ctx context.Context, task *Task) error { handler: HandlerFunc(func(ctx context.Context, task *Task) error {
return SkipRetry // return SkipRetry without wrapping return SkipRetry // return SkipRetry without wrapping
}), }),
wait: 2 * time.Second, wait: 2 * time.Second,
wantRetry: []base.Z{}, wantErrMsg: SkipRetry.Error(),
wantArchived: []*base.TaskMessage{ wantRetry: []*base.TaskMessage{},
h.TaskMessageWithError(*m1, SkipRetry.Error()), wantArchived: []*base.TaskMessage{m1, m2},
h.TaskMessageWithError(*m2, SkipRetry.Error()),
},
wantErrCount: 2, // ErrorHandler should still be called with SkipRetry error wantErrCount: 2, // ErrorHandler should still be called with SkipRetry error
}, },
{ {
desc: "Should skip retry errored tasks (with error wrapping)", desc: "Should skip retry errored tasks (with error wrapping)",
pending: []*base.TaskMessage{m1, m2}, pending: []*base.TaskMessage{m1, m2},
incoming: []*base.TaskMessage{}, delay: time.Minute,
delay: time.Minute,
handler: HandlerFunc(func(ctx context.Context, task *Task) error { handler: HandlerFunc(func(ctx context.Context, task *Task) error {
return wrappedSkipRetry return wrappedSkipRetry
}), }),
wait: 2 * time.Second, wait: 2 * time.Second,
wantRetry: []base.Z{}, wantErrMsg: wrappedSkipRetry.Error(),
wantArchived: []*base.TaskMessage{ wantRetry: []*base.TaskMessage{},
h.TaskMessageWithError(*m1, wrappedSkipRetry.Error()), wantArchived: []*base.TaskMessage{m1, m2},
h.TaskMessageWithError(*m2, wrappedSkipRetry.Error()),
},
wantErrCount: 2, // ErrorHandler should still be called with SkipRetry error wantErrCount: 2, // ErrorHandler should still be called with SkipRetry error
}, },
} }
@ -415,24 +408,34 @@ func TestProcessorRetry(t *testing.T) {
p.handler = tc.handler p.handler = tc.handler
p.start(&sync.WaitGroup{}) p.start(&sync.WaitGroup{})
for _, msg := range tc.incoming { now := time.Now() // time when processor is running
err := rdbClient.Enqueue(msg)
if err != nil {
p.shutdown()
t.Fatal(err)
}
}
time.Sleep(tc.wait) // FIXME: This makes test flaky. time.Sleep(tc.wait) // FIXME: This makes test flaky.
p.shutdown() p.shutdown()
cmpOpt := h.EquateInt64Approx(1) // allow up to a second difference in zset score cmpOpt := h.EquateInt64Approx(int64(tc.wait.Seconds())) // allow up to a wait-second difference in zset score
gotRetry := h.GetRetryEntries(t, r, base.DefaultQueueName) gotRetry := h.GetRetryEntries(t, r, base.DefaultQueueName)
if diff := cmp.Diff(tc.wantRetry, gotRetry, h.SortZSetEntryOpt, cmpOpt); diff != "" { var wantRetry []base.Z // Note: construct wantRetry here since `LastFailedAt` and ZSCORE is relative to each test run.
for _, msg := range tc.wantRetry {
wantRetry = append(wantRetry,
base.Z{
Message: h.TaskMessageAfterRetry(*msg, tc.wantErrMsg),
Score: now.Add(tc.delay).Unix(),
})
}
if diff := cmp.Diff(wantRetry, gotRetry, h.SortZSetEntryOpt, cmpOpt); diff != "" {
t.Errorf("%s: mismatch found in %q after running processor; (-want, +got)\n%s", tc.desc, base.RetryKey(base.DefaultQueueName), diff) t.Errorf("%s: mismatch found in %q after running processor; (-want, +got)\n%s", tc.desc, base.RetryKey(base.DefaultQueueName), diff)
} }
gotDead := h.GetArchivedMessages(t, r, base.DefaultQueueName) gotArchived := h.GetArchivedEntries(t, r, base.DefaultQueueName)
if diff := cmp.Diff(tc.wantArchived, gotDead, h.SortMsgOpt); diff != "" { var wantArchived []base.Z // Note: construct wantArchived here since `LastFailedAt` and ZSCORE is relative to each test run.
for _, msg := range tc.wantArchived {
wantArchived = append(wantArchived,
base.Z{
Message: h.TaskMessageWithError(*msg, tc.wantErrMsg),
Score: now.Unix(),
})
}
if diff := cmp.Diff(wantArchived, gotArchived, h.SortZSetEntryOpt, cmpOpt); diff != "" {
t.Errorf("%s: mismatch found in %q after running processor; (-want, +got)\n%s", tc.desc, base.ArchivedKey(base.DefaultQueueName), diff) t.Errorf("%s: mismatch found in %q after running processor; (-want, +got)\n%s", tc.desc, base.ArchivedKey(base.DefaultQueueName), diff)
} }