Fixes
- Saga compensation and cancellation: embedded
compensate()now runs under a cancellation shield, as the PHP and Python SDK sagas do. A cooperative cancellation request that arrives during compensation no longer skips the remaining compensations. Cleanup deadlines, termination and run timeouts still apply (#872). - Updates accepted while a run is closing: an update accepted while the workflow task that completes the run is running now gets one delivery turn before the run closes, as a signal does. Its handler runs and the caller gets its result instead of a closed-run failure (#890).
- Activity attempt budgets: a new activity or local activity with
maxAttemptsbelow 1 now fails the run with a clear message, because the budget counts the first attempt. Previously it silently ran once. For unlimited attempts, omitmaxAttemptsand set the activity class$triesto 0. Histories that recordedmaxAttempts: 0under an earlier release keep replaying after the upgrade (#860). - Determinism scan: the embedded boot scan now flags
new DateTime(),new DateTimeImmutable(),new Carbon()andnew CarbonImmutable()when they read the current time, plustoday(),shuffle,array_randandstr_shuffle. Fixed dates are not flagged (#888). - Service-mode payload limits: activity, child and continue-as-new arguments and workflow results from SDK workers now get the same payload size limit embedded workflows have. Oversized payloads refuse the whole completion with the typed structural-limit failure (#865).
Compatibility
No database migration, history format or dependency floor change.