Skip to content

Commit

Permalink
fix double firing of schedules at initial interval (#3624)
Browse files Browse the repository at this point in the history
  • Loading branch information
fubhy authored Sep 17, 2024
1 parent ae36fa6 commit 10bf621
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/blue-comics-prove.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

Fixed double firing of cron schedules in cases where the current time matched the initial interval.
17 changes: 10 additions & 7 deletions packages/effect/src/internal/schedule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -433,21 +433,24 @@ export const cron = (expression: string | Cron.Cron): Schedule.Schedule<[number,
const cron = parsed.right
const date = new Date(now)

let next: number
if (initial && Cron.match(cron, date)) {
next = now
} else {
const result = Cron.next(cron, date)
next = result.getTime()
const next = now
const start = beginningOfMinute(next)
const end = endOfMinute(next)
return core.succeed([
[false, [next, start, end]],
[start, end],
ScheduleDecision.continueWith(Interval.make(start + 60000, end + 60000))
])
}

const next = Cron.next(cron, date).getTime()
const start = beginningOfMinute(next)
const end = endOfMinute(next)
const interval = Interval.make(start, end)
return core.succeed([
[false, [next, start, end]],
[start, end],
ScheduleDecision.continueWith(interval)
ScheduleDecision.continueWith(Interval.make(start, end))
])
}
)
Expand Down
24 changes: 24 additions & 0 deletions packages/effect/test/Schedule.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,30 @@ describe("Schedule", () => {
}))
})
describe("cron-like scheduling - repeats at point of time (minute of hour, day of week, ...)", () => {
it.effect("recur every minute after initial interval using cron", () =>
Effect.gen(function*($) {
const ref = yield* $(Ref.make<ReadonlyArray<string>>([]))
yield* $(TestClock.setTime(new Date(2024, 0, 1, 0, 0, 35).getTime()))
const schedule = Schedule.cron("* * * * *")
yield* $(
TestClock.currentTimeMillis,
Effect.tap((instant) => Ref.update(ref, Array.append(format(instant)))),
Effect.repeat(schedule),
Effect.fork
)
yield* $(TestClock.adjust("5 minutes"))
const result = yield* $(Ref.get(ref))
const expected = [
"Mon Jan 01 2024 00:00:35",
"Mon Jan 01 2024 00:01:00",
"Mon Jan 01 2024 00:02:00",
"Mon Jan 01 2024 00:03:00",
"Mon Jan 01 2024 00:04:00",
"Mon Jan 01 2024 00:05:00"
]
assert.deepStrictEqual(result, expected)
}))

it.effect("recur at time matching cron expression", () =>
Effect.gen(function*($) {
const ref = yield* $(Ref.make<ReadonlyArray<string>>([]))
Expand Down

0 comments on commit 10bf621

Please sign in to comment.