Skip to content

Run PHP schedule specifications, policies and namespaces natively - #570

Merged
rmcdaniel merged 3 commits into
mainfrom
rust-325-schedule-cron
Oct 21, 2026
Merged

rmcdaniel merged 3 commits into
mainfrom
rust-325-schedule-cron

Conversation

@rmcdaniel

Copy link
Copy Markdown
Member

Part of #325.

Native schedules now run PHP's schedule definitions as published Server 2.5.14 runs them. Before this change, native accepted only a narrow subset.

What changes

  • Cron. schedule_cron.rs ports dragonmantank/cron-expression 3.6.0: validation, aliases, names, ranges, steps, lists, L, W, # and ?, the 1,000-step search limit, and PHP DateTime behaviour around daylight-saving changes.
  • Zones. schedule_zones.rs reads zone names as new DateTimeZone() does: numeric offsets, PHP's 144 abbreviations, and IANA names in any case.
  • Specifications. schedule_spec.rs computes the next fire time across several cron expressions and offset intervals, using PHP's DateInterval grammar.
  • Schedules. Creation follows PHP's Laravel rules and messages. Describe, history, pause, resume, trigger and delete match PHP's response shapes.
    • Triggers support all six overlap policies, buffering, closing the other run, run quotas, jitter, memo and note.
    • The tick drains buffered actions before due schedules.
    • Schedules are namespace-scoped and start runs in their own namespace.

Deliberate differences

  • Resuming an active schedule returns 409 schedule_not_paused; PHP returns an unhandled 500.
  • When another native node has already fired an occurrence, the tick skips it silently instead of recording stale_occurrence.
  • Plain JSON array input and search attributes are refused, as native start refuses them.
  • Native uses newer IANA rules (2026e) than PHP's bundled 2026.1 data for six zones: Casablanca, El Aaiun, Edmonton, Inuvik, Vancouver and Winnipeg.
  • Fixed offsets of 26 hours or more are refused. PHP accepts offsets up to 100 hours.

Evidence

  • scripts/conformance/cron-oracle regenerates three corpora byte for byte from the frozen PHP image. Native matches all of them:
    • 1,200 cron cases;
    • 1,068 zone spellings;
    • 600 whole specifications.
  • The new schedule-policies fixture sends 60 requests and compares every response with reviewed published-PHP output. It passed locally on published PHP, embedded and this branch's native build; native from main fails it.
  • A PHP-on-PostgreSQL HTTP diff matched native on 72 responses. The only differences were the two refusals listed above.
  • Local tests passed: the lib suite (154 tests), the SQLite execution suite (298 tests), the schedule and namespace tests on PostgreSQL, MySQL 8.4 and MariaDB 10.11, and all 176 contract unit tests.

Next: update, listing (visibility query and page tokens) and backfill; then narrowing the takeover schedule refusal (#568).

🤖 Generated with Claude Code

Native schedules were a bounded subset: one UTC interval of a day or two
seconds, the skip policy, no jitter, at most one run, the default namespace.
They now follow published PHP 2.5.14:

- cron expressions exactly as dragonmantank/cron-expression 3.6.0 evaluates
  them, including PHP's DateTime rules around daylight-saving changes,
  time zone names as new DateTimeZone() reads them, and computeNextFireAt
  over cron expressions and offset intervals;
- creation with PHP's Laravel validation rules, messages and normalization,
  any schedule id, jitter, run quota, memo, note and creation paused;
- triggerDetailed and the tick: all six overlap policies, buffering and its
  drain, closing the other run, stale and exhausted occurrences, failures,
  the recent-actions ring and the next fire time after each fire;
- PHP's description, history snapshot and history page shapes, pause and
  resume notes, and namespace-scoped schedules.

scripts/conformance/cron-oracle regenerates the committed corpora of PHP's
own answers from the frozen image; native matches all of them. The new
schedule-policies fixture compares 60 responses with a reviewed copy of
published PHP's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rmcdaniel

Copy link
Copy Markdown
Member Author

Cancelled this head's CI runs (39549600277, 39549600278) without results. #566 merged and left this branch in conflict on the port log, and the merge train updates one PR at a time. CI will run again when this branch is brought up to date in its turn.

durable-workflow-ops and others added 2 commits October 21, 2026 06:59
#568's takeover schedule check is narrowed to what native still cannot run
now that it runs PHP schedules: search attributes, visibility labels, queue
routing, an unknown status, a definition native's creation refuses and a
specification it cannot evaluate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	.github/workflows/server-parity.yml
#	docs/rust-server-port.md
#	scripts/conformance/server-parity/contract.mjs
#	scripts/conformance/server-parity/probe.php
@rmcdaniel

Copy link
Copy Markdown
Member Author

Merged main after #566, #567, #568, #558 and #572 (f49568f). The takeover schedule check from #568 is narrowed in the merge to what native still cannot run. The Shared Server fixtures trigger path list now gives each new contract test its own entry: #570's original edit and #572 had each appended its test to an existing entry. Lib (156), schedule and signal tests pass locally, along with the 5,058 contract unit tests.

@sonarqubecloud

Copy link
Copy Markdown

@rmcdaniel
rmcdaniel merged commit 2b62310 into main Oct 21, 2026
10 checks passed
@rmcdaniel
rmcdaniel deleted the rust-325-schedule-cron branch October 21, 2026 07:48
rmcdaniel added a commit that referenced this pull request Oct 21, 2026
…fication-fix

Fix main's database parity jobs after #570 and #572
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