Skip to content

Commit 1a713b0

Browse files
committed
Workers do exponential backoff
1 parent 461ec42 commit 1a713b0

File tree

2 files changed

+37
-17
lines changed

2 files changed

+37
-17
lines changed

internal-packages/redis-worker/src/worker.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ describe("Worker", () => {
7575
testJob: {
7676
schema: z.object({ value: z.number() }),
7777
visibilityTimeoutMs: 5000,
78-
retry: { maxAttempts: 3, minDelayMs: 10 },
78+
retry: { maxAttempts: 3, minTimeoutInMs: 10, maxTimeoutInMs: 10 },
7979
},
8080
},
8181
jobs: {

internal-packages/redis-worker/src/worker.ts

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { Logger } from "@trigger.dev/core/logger";
2+
import { type RetryOptions } from "@trigger.dev/core/v3/schemas";
3+
import { calculateNextRetryDelay } from "@trigger.dev/core/v3";
24
import { type RedisOptions } from "ioredis";
35
import os from "os";
46
import { Worker as NodeWorker } from "worker_threads";
@@ -9,11 +11,7 @@ type WorkerCatalog = {
911
[key: string]: {
1012
schema: z.ZodFirstPartySchemaTypes | z.ZodDiscriminatedUnion<any, any>;
1113
visibilityTimeoutMs: number;
12-
retry: {
13-
maxAttempts: number;
14-
minDelayMs?: number;
15-
scaleFactor?: number;
16-
};
14+
retry: RetryOptions;
1715
};
1816
};
1917

@@ -25,6 +23,7 @@ type JobHandler<Catalog extends WorkerCatalog, K extends keyof Catalog> = (param
2523
id: string;
2624
payload: z.infer<Catalog[K]["schema"]>;
2725
visibilityTimeoutMs: number;
26+
attempt: number;
2827
}) => Promise<void>;
2928

3029
type WorkerOptions<TCatalog extends WorkerCatalog> = {
@@ -148,7 +147,7 @@ class Worker<TCatalog extends WorkerCatalog> {
148147
}
149148

150149
await Promise.all(
151-
items.map(async ({ id, job, item, visibilityTimeoutMs }) => {
150+
items.map(async ({ id, job, item, visibilityTimeoutMs, attempt }) => {
152151
const catalogItem = this.options.catalog[job as any];
153152
const handler = this.jobs[job as any];
154153
if (!handler) {
@@ -157,7 +156,7 @@ class Worker<TCatalog extends WorkerCatalog> {
157156
}
158157

159158
try {
160-
await handler({ id, payload: item, visibilityTimeoutMs });
159+
await handler({ id, payload: item, visibilityTimeoutMs, attempt });
161160
await this.queue.ack(id);
162161
} catch (error) {
163162
this.logger.error(`Error processing item, it threw an error:`, {
@@ -170,7 +169,23 @@ class Worker<TCatalog extends WorkerCatalog> {
170169
});
171170
// Requeue the failed item with a delay
172171
try {
173-
const retryDelay = catalogItem.retry.minDelayMs ?? 1_000;
172+
attempt = attempt + 1;
173+
174+
const retryDelay = calculateNextRetryDelay(catalogItem.retry, attempt);
175+
176+
if (!retryDelay) {
177+
this.logger.error(`Failed item ${id} has reached max attempts, acking.`, {
178+
name: this.options.name,
179+
id,
180+
job,
181+
item,
182+
visibilityTimeoutMs,
183+
attempt,
184+
});
185+
await this.queue.ack(id);
186+
return;
187+
}
188+
174189
const retryDate = new Date(Date.now() + retryDelay);
175190
this.logger.info(`Requeued failed item ${id} with delay`, {
176191
name: this.options.name,
@@ -180,23 +195,28 @@ class Worker<TCatalog extends WorkerCatalog> {
180195
retryDate,
181196
retryDelay,
182197
visibilityTimeoutMs,
198+
attempt,
183199
});
184200
await this.queue.enqueue({
185201
id,
186202
job,
187203
item,
188204
availableAt: retryDate,
205+
attempt,
189206
visibilityTimeoutMs,
190207
});
191208
} catch (requeueError) {
192-
this.logger.error(`Failed to requeue item, threw error:`, {
193-
name: this.options.name,
194-
id,
195-
job,
196-
item,
197-
visibilityTimeoutMs,
198-
error: requeueError,
199-
});
209+
this.logger.error(
210+
`Failed to requeue item, threw error. Will automatically get rescheduled after the visilibity timeout.`,
211+
{
212+
name: this.options.name,
213+
id,
214+
job,
215+
item,
216+
visibilityTimeoutMs,
217+
error: requeueError,
218+
}
219+
);
200220
}
201221
}
202222
})

0 commit comments

Comments
 (0)