Nobody has started this yet — be first.
Business impact
This is the single most severe bug in this set: it silently disables the entire product. Chronos exists to run scheduled jobs; if the materializer never creates a job_run for a cron job's due occurrences, nothing is ever scheduled, ever, for any job, on any instance -- and there is no error anywhere. Tick() returns nil. Leader election is healthy. The HTTP API is healthy. /readyz reports a leader. Every dashboard looks green while the core function of the service has quietly stopped working entirely -- exactly the kind of bug that survives a superficial health check and is only discovered when a customer notices their job hasn't fired in a day.
Problem
pkg/cron/materializer.go's materializeCron caps how far back it will "catch up" missed occurrences after a leader election gap: cutoff := now.Add(24 * time.Hour). cutoff is a positive offset, putting it in the future. The loop only ever runs while next is <= now (for !next.After(now)), so every candidate occurrence is by construction earlier than a cutoff that's 24 hours in the future. next.After(cutoff) is therefore never true, and InsertIfAbsent is never called.
Current behavior
After Tick() against an every-minute cron job created 5 minutes ago, 0 job_runs exist for it, indefinitely, no matter how long you wait.
Expected behavior
The catch-up cap should discard occurrences older than 24 hours (protecting against a long-dead leader flooding the table with a huge backlog), while still materializing normal, recent due occurrences. cutoff should be now - 24 hours, not now + 24 hours.
Steps to reproduce
Why this matters
A sign error on a duration offset is easy to introduce and, because the surrounding logic (for !next.After(now), if next.After(cutoff)) reads correctly in isolation, easy to miss without tracing through what values cutoff can actually take relative to next.
Suggested approach
Read the comment directly above the cutoff line -- it says what the cutoff is supposed to represent ("anything older than 24h of missed ticks is skipped"). Check whether the code one line below matches that description.
Acceptance criteria
Verification
TEST_DATABASE_URL="postgresql://chronos:chronos@localhost:5432/chronos?sslmode=disable" go test ./tickets/tests/... -run TestTicket10 -v
Hints (0/2)
Try it without hints first — the reading is the exercise.
Working on this ticket
Work on a branch named for the ticket — that's what you'll submit.
Branch off your fork
Sign in to create it automatically, or do it yourself:
$git checkout -b fix/materializer-cutoff-signFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin fix/materializer-cutoff-signSubmit it below
Paste your fork URL and the branch name, with a short write-up of the root cause.
Questions
Ask about anything unclear in the ticket — the maintainer and anyone who has solved it can answer. Please don't post full solutions.
Sign in to ask a question or reply.
Sign inhttp://localhost:8081app-1http://localhost:8082app-2http://localhost:8090curl localhost:8081/healthzcurl localhost:8081/readyzWork the tickets in tickets/docs/ (ordered easy → hard); each names one Go test in tickets/tests/. Most tickets need a real Postgres (tickets 4, 11, and 18 are pure-function tests and do not):
export TEST_DATABASE_URL="postgresql://chronos:chronos@localhost:5432/chronos?sslmode=disable"
go test ./tickets/tests/... -run TestTicket08 -v # a single ticket
./tickets/run_tickets.sh # all 20, clean pass/fail summary
Use -race when working on tickets 15, 16, or 17 (the concurrency ones) -- run_tickets.sh already does this for every ticket. Tickets 15 and 16 are adjacent bugs in the same function (pkg/leader/leader.go's lock-release path); fix ticket 16 first, since ticket 15's test keeps failing for ticket 16's reason until that one is fixed too.
Level 1
Fix a bug
Read existing behaviour, correct it.