fix(api): validate time slot schedules before handing them to the scheduler - #2013
Open
chrisbenincasa wants to merge 1 commit into
Open
fix(api): validate time slot schedules before handing them to the scheduler#2013chrisbenincasa wants to merge 1 commit into
chrisbenincasa wants to merge 1 commit into
Conversation
…eduler
Every numeric field on a time slot schedule was a bare z.number() and slots had
no minimum length, so several inputs reached the scheduler that it mishandles
rather than rejects. Probing each one:
startTime: 1234.567 an infinite loop. The scheduling loop is synchronous
despite the enclosing async, so it blocks the event
loop outright -- the test runner's own timeout never
fires and the process has to be killed. The worker
pool's timeoutPromise rejects the caller while the
thread keeps burning a core, so N such requests
permanently exhaust an N worker pool.
padMs: 0 reports success and returns a lineup whose durations
are all NaN.
maxDays: -1 reports success and returns zero lineup items.
maxDays: 0 returns half the expected items.
slots: [] throws "Could not find a suitable slot", the same
message an out-of-period offset produces, so the log
cannot tell the two apart.
Add StrictTimeSlotScheduleSchema and use it for the request body.
TimeSlotScheduleSchema itself has to stay permissive. It also feeds
LineupScheduleSchema inside CondensedChannelProgrammingSchema, which is both
persisted and used to serialize channel responses, so tightening it would make
a channel already holding one of these values fail response serialization and
stop loading entirely -- worse than the bug. This is the same split already
used for StrictChannelIconSchema.
The bounds are startTime a whole number within the period, padMs and maxDays
positive, latenessMs non-negative, and at least one slot. A test asserts the
permissive schema still accepts every case the strict one rejects, so the
distinction cannot be erased by accident later.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Every numeric field on
TimeSlotScheduleSchemais a barez.number(), andslotshas nominimum length. Several inputs therefore reach the scheduler, which mishandles rather than
rejects them. Each row below was reproduced:
startTime: 1234.567padMs: 0NaNmaxDays: -1maxDays: 0slots: []Could not find a suitable slot— the same message an out-of-period offset produces, so the log can't tell them apartThe first is the serious one. The scheduling loop is synchronous despite the enclosing
async, so it blocks the event loop outright: vitest's own 15-second test timeout neverfired and the process had to be killed at 60 seconds. The worker pool's
timeoutPromiserejects the caller's promise after 60s while the thread keeps burning a core forever, so N
such requests permanently exhaust an N-worker pool.
Fix
Add
StrictTimeSlotScheduleSchemaand use it for the request body atchannelsApi.ts:743.TimeSlotScheduleSchemaitself is deliberately left permissive. It feedsLineupScheduleSchemainsideCondensedChannelProgrammingSchema, which is both persistedand used to serialize channel responses — so tightening it would make a channel already
holding one of these values fail response serialization and stop loading entirely, which is
worse than the bug. This is the same split already used for
StrictChannelIconSchemaandChannelIconSchema.Bounds:
startTimea whole number within the period (viasuperRefine, since the validrange depends on
period),padMsandmaxDayspositive,latenessMsnon-negative, atleast one slot.
Note for review
This rejects requests the API currently accepts. That should only affect payloads that
already produce a broken schedule, but it is a behaviour change at the boundary and is the
reason this is split from the scheduler fix in #2012, which stands on its own.
Test plan
NaNwas already excluded byz.number(); recorded as such rather than claimed as a fix🤖 Generated with Claude Code