Skip to content

Native schedule list, update and backfill - #573

Merged
rmcdaniel merged 2 commits into
mainfrom
rust-325-schedule-list-update
Oct 21, 2026
Merged

rmcdaniel merged 2 commits into
mainfrom
rust-325-schedule-list-update

Conversation

@rmcdaniel

Copy link
Copy Markdown
Member

Part of #325. Follows #570, which has merged.

Native now lists, updates and backfills schedules as published Server 2.5.14 does.

What changes

  • Listing (GET /api/schedules). Supports PHP's filters with Laravel's validation messages and PHP's refusal bodies, including last_safe_cursor.
    • The schedule visibility query accepts equality predicates joined by AND. They work on ScheduleId, Status, WorkflowType, TaskQueue, Note and registered search attributes.
    • Continuation tokens are signed as PHP signs them, using DW_SERVER_KEY or APP_KEY. When neither is set, native uses its auth token, not a per-container key, so tokens survive restarts and work on every node. Each token is bound to its namespace and filters, and is refused once its cursor is gone.
    • The SQL is built from fixed fragments with bound values on every database family.
  • Update (PUT /api/schedules/{id}). Merges the action with the stored one, recomputes the run quota and next fire time, and records PHP's changed_fields.
  • Backfill (POST /api/schedules/{id}/backfill). Fires every occurrence in the range once, from the start time up to but not including the end time, as triggerForBackfill does.
    • Buffering policies start every occurrence, already fired occurrences are skipped, and the run quota ends the backfill.
    • Fire times carry PHP's offsets: the schedule zone's for a cron occurrence, UTC for an interval.
  • Validation fix. Laravel sizes a non-numeric value under a numeric rule by its string length. Native now does the same, so page_size=x reports only the integer rule.

Deliberate differences

  • Backfill times must be ISO-8601. PHP's other strtotime forms, such as +1 day or @timestamp, get the date validation message.
  • A backfill range with more than 10,000 occurrences is refused with 422 backfill_range_too_large. PHP has no limit.
  • An update to a specification that cannot be evaluated returns 422. PHP returns an unhandled 500.

Evidence

  • New cron-oracle/backfill-dates.php: PHP's date rule and instant for 700 seeded strings. Native refuses everything PHP refuses and matches every instant to the microsecond.
  • The next-fire corpus now also records PHP's offsets (600 cases), and native matches all of them.
  • New schedule-catalog parity fixture (72 requests, with a reviewed PHP copy). Locally, published PHP, embedded and native pass it, and PHP and native agree on every normalized response.
  • A PHP-on-PostgreSQL HTTP diff matched native on 81 responses. The only differences were the deliberate ones above.
  • Schedule tests pass on SQLite, PostgreSQL, MySQL 8.4 and MariaDB 10.11.

🤖 Generated with Claude Code

durable-workflow-ops and others added 2 commits October 21, 2026 06:07
GET /api/schedules follows ScheduleController::index: status and workflow
type filters, the schedule visibility query (equality predicates joined by
AND on schedule fields and registered search attributes), Laravel's
messages, PHP's refusal bodies and continuation tokens signed with
DW_SERVER_KEY or APP_KEY, bound to the namespace, filters and a cursor that
must still exist. PUT /api/schedules/{id} merges the action and records
PHP's changed fields. POST /api/schedules/{id}/backfill triggers each
occurrence in the range as triggerForBackfill does, with PHP's fire times
and offsets.

Backfill times are read as ISO-8601 exactly as PHP's date rule and
DateTimeImmutable read them, checked against a 700-case oracle corpus.
Other strtotime spellings are refused. Ranges over 10,000 occurrences
are refused instead of running unbounded, and an update to a spec that
cannot be evaluated is a 422 where PHP returns 500.

Laravel sizes a non-numeric value under a numeric rule by its length;
the shared rules engine now does too.

The new schedule-catalog fixture compares 72 responses with a reviewed
copy of published PHP's. The schedule probe replays its whole sequence
in a new namespace when published PHP on SQLite records its own lock
failure inside a response.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t-update

# Conflicts:
#	.github/workflows/server-parity.yml
#	scripts/conformance/server-parity/contract.mjs
#	scripts/conformance/server-parity/probe.php
@rmcdaniel
rmcdaniel enabled auto-merge October 21, 2026 07:51
@sonarqubecloud

Copy link
Copy Markdown

@rmcdaniel
rmcdaniel merged commit 83700f0 into main Oct 21, 2026
16 of 22 checks passed
@rmcdaniel
rmcdaniel deleted the rust-325-schedule-list-update branch October 21, 2026 08:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants