Skip to content

Commit 5ef7889

Browse files
committed
fix(adapter): preserve schedule runCount on schedule upsert
1 parent 17b6afa commit 5ef7889

File tree

4 files changed

+50
-10
lines changed

4 files changed

+50
-10
lines changed

src/drivers/fake_adapter.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ export class FakeAdapter implements Adapter {
345345

346346
async upsertSchedule(config: ScheduleConfig): Promise<string> {
347347
const id = config.id ?? randomUUID()
348+
const existing = this.#schedules.get(id)
348349
const now = new Date()
349350

350351
const schedule: ScheduleData = {
@@ -357,11 +358,11 @@ export class FakeAdapter implements Adapter {
357358
from: config.from ?? null,
358359
to: config.to ?? null,
359360
limit: config.limit ?? null,
360-
runCount: 0,
361-
nextRunAt: null, // Will be calculated by the caller
362-
lastRunAt: null,
361+
runCount: existing?.runCount ?? 0,
362+
nextRunAt: existing?.nextRunAt ?? null, // Will be (re)calculated by the caller
363+
lastRunAt: existing?.lastRunAt ?? null,
363364
status: 'active',
364-
createdAt: now,
365+
createdAt: existing?.createdAt ?? now,
365366
}
366367

367368
this.#schedules.set(id, schedule)

src/drivers/redis_adapter.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -704,15 +704,20 @@ export class RedisAdapter implements Adapter {
704704
const id = config.id ?? randomUUID()
705705
const now = Date.now()
706706
const scheduleKey = `${schedulesKey}::${id}`
707+
const [existingRunCount, existingCreatedAt] = await this.#connection.hmget(
708+
scheduleKey,
709+
'run_count',
710+
'created_at'
711+
)
707712

708713
const scheduleData: Record<string, string> = {
709714
id,
710715
name: config.name,
711716
payload: JSON.stringify(config.payload),
712717
timezone: config.timezone,
713718
status: 'active',
714-
run_count: '0',
715-
created_at: now.toString(),
719+
run_count: existingRunCount ?? '0',
720+
created_at: existingCreatedAt ?? now.toString(),
716721
}
717722

718723
if (config.cronExpression !== undefined) scheduleData.cron_expression = config.cronExpression

tests/_mocks/memory_adapter.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ export class MemoryAdapter implements Adapter {
259259

260260
async upsertSchedule(config: ScheduleConfig): Promise<string> {
261261
const id = config.id ?? randomUUID()
262+
const existing = this.#schedules.get(id)
262263
const now = new Date()
263264

264265
const schedule: ScheduleData = {
@@ -271,11 +272,11 @@ export class MemoryAdapter implements Adapter {
271272
from: config.from ?? null,
272273
to: config.to ?? null,
273274
limit: config.limit ?? null,
274-
runCount: 0,
275-
nextRunAt: null, // Will be calculated by the caller
276-
lastRunAt: null,
275+
runCount: existing?.runCount ?? 0,
276+
nextRunAt: existing?.nextRunAt ?? null, // Will be (re)calculated by the caller
277+
lastRunAt: existing?.lastRunAt ?? null,
277278
status: 'active',
278-
createdAt: now,
279+
createdAt: existing?.createdAt ?? now,
279280
}
280281

281282
this.#schedules.set(id, schedule)

tests/_utils/register_driver_test_suite.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,39 @@ export function registerDriverTestSuite(options: DriverTestSuiteOptions) {
11671167
assert.isNull(schedule!.limit)
11681168
})
11691169

1170+
test('upsertSchedule should preserve runtime runCount when id exists', async ({ assert }) => {
1171+
const adapter = await options.createAdapter()
1172+
1173+
await adapter.upsertSchedule({
1174+
id: 'upsert-preserve-run-count',
1175+
name: 'TestJob',
1176+
payload: { version: 1 },
1177+
everyMs: 5000,
1178+
timezone: 'UTC',
1179+
})
1180+
1181+
await adapter.updateSchedule('upsert-preserve-run-count', {
1182+
runCount: 3,
1183+
lastRunAt: new Date(),
1184+
nextRunAt: new Date(Date.now() + 60_000),
1185+
})
1186+
1187+
await adapter.upsertSchedule({
1188+
id: 'upsert-preserve-run-count',
1189+
name: 'TestJob',
1190+
payload: { version: 2 },
1191+
cronExpression: '*/5 * * * *',
1192+
timezone: 'Europe/Paris',
1193+
})
1194+
1195+
const schedule = await adapter.getSchedule('upsert-preserve-run-count')
1196+
assert.isNotNull(schedule)
1197+
assert.deepEqual(schedule!.payload, { version: 2 })
1198+
assert.equal(schedule!.cronExpression, '*/5 * * * *')
1199+
assert.isNull(schedule!.everyMs)
1200+
assert.equal(schedule!.runCount, 3)
1201+
})
1202+
11701203
test('getSchedule should return null for non-existent schedule', async ({ assert }) => {
11711204
const adapter = await options.createAdapter()
11721205

0 commit comments

Comments
 (0)