fix(schedule): close recurring gate edge cases
This commit is contained in:
@@ -38,6 +38,12 @@ const LOCAL_TIME = /^(?<hour>\d{2}):(?<minute>\d{2}):(?<second>\d{2})(?:\.(?<fra
|
||||
const IANA_ZONE = /^[A-Za-z][A-Za-z0-9_+.-]*(?:\/[A-Za-z0-9_+.-]+)+$/
|
||||
const OFFSET_NAME = /^GMT(?:(?<sign>[+-])(?<hour>\d{2}):(?<minute>\d{2})(?::(?<second>\d{2}))?)?$/
|
||||
|
||||
/** Whether the durable recurring gate has no four-digit-year admission left. */
|
||||
export function isRecurringGateExhausted(lastAcceptedAt: string | undefined): boolean {
|
||||
return lastAcceptedAt !== undefined
|
||||
&& Date.parse(lastAcceptedAt) + MIN_RECURRING_INTERVAL_SECONDS * 1_000 > MAX_FOUR_DIGIT_YEAR_MS
|
||||
}
|
||||
|
||||
/** Error from malformed or transition-invalid durable Schedule data. */
|
||||
export class ScheduleLogError extends Error {
|
||||
/** Stable machine-readable error code. */
|
||||
@@ -642,8 +648,7 @@ export function foldScheduleEvents(
|
||||
}
|
||||
}
|
||||
// A gate beyond the supported time profile can never admit another Every batch.
|
||||
if (lastRecurringAcceptedAt !== undefined
|
||||
&& Date.parse(lastRecurringAcceptedAt) + MIN_RECURRING_INTERVAL_SECONDS * 1_000 > MAX_FOUR_DIGIT_YEAR_MS) {
|
||||
if (isRecurringGateExhausted(lastRecurringAcceptedAt)) {
|
||||
for (const [id, record] of active) {
|
||||
if (record.kind === 'every') active.delete(id)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
createAtScheduleRecord,
|
||||
createEveryScheduleRecord,
|
||||
foldScheduleEvents,
|
||||
isRecurringGateExhausted,
|
||||
MIN_RECURRING_INTERVAL_SECONDS,
|
||||
ScheduleId,
|
||||
ScheduleInputError,
|
||||
@@ -466,6 +467,13 @@ export function registerScheduleTools(
|
||||
notifyDurableChange()
|
||||
const folded = foldForTool(agent)
|
||||
if (isToolError(folded)) return folded
|
||||
if (args.every_seconds !== undefined
|
||||
&& isRecurringGateExhausted(folded.lastRecurringAcceptedAt)) {
|
||||
return {
|
||||
code: 'time_out_of_range',
|
||||
message: 'The scheduled time must be representable as a four-digit-year RFC 3339 UTC instant.',
|
||||
}
|
||||
}
|
||||
const id = allocateScheduleId(folded)
|
||||
let record: ScheduleRecord
|
||||
let timeZone: AtTimeZoneContext | undefined
|
||||
|
||||
Reference in New Issue
Block a user