Repository navigation
Add firefly/orchestration: sagas, TCC and durable workflows - #15
Merged
Merged
Conversation
added 30 commits
October 12, 2026 18:52
…e library, deptrac and the installer
…nd the exception family
…of exhausting memory mid-checkpoint
… and refuse non-finite floats and invalid UTF-8
… step invoker and lifecycle callbacks
…vents and the trigger gateway
…headers on lifecycle events
…ache providers, and a re-entrant execution lock
… the dead-letter queue and back-pressure admission
…stry, the builder DSL and saga results
…ensation error handlers
…y when the saga has none configured
…eaker policy stops the compensation sweep
…idempotency, compensation, dead letters, resume
… of the members that completed
…ot undo and tolerate optional members that cannot start
…phase retries, phase checkpoints and composition
… a resume never retries it or reports CONFIRMED
… resume an interrupted cancel on request as one
…s interrupted, with a null try result
…waits, children and queries, and the builder DSL
… time and refuse a manifest wait without a known kind
…, continue-as-new and queries, plus dead-letter retry
… re-driven by its children, and keep the tick going past an execution it cannot drive
… keep the continue-as-new origin out of children, fail a parent whose child cannot start, and refuse a taken workflow correlation id
…nued as new still wakes its parent, keep the report and deadline on a search-attribute upsert, back off due workflows the tick cannot drive, and lock the ASYNC start
…ore, proven on PostgreSQL, MySQL, MariaDB and SQLite
added 28 commits
October 12, 2026 21:24
…anifest that firefly:cache emits
…e definitions at boot, and start executions from EDA triggers
…the event id and carry the envelope headers, so a redelivered event is acknowledged instead of starting the definition again
…utions, the scheduled tick and sweep, and scheduled orchestrations
…covery instead of driving the workflow forward
…recovery acts, so a run that finished or checkpointed while the sweep waited is skipped instead of undone or driven twice
… and the checkpoint in wakeAt, so the tick still wakes that waiting workflow
…mponent, and commands to list, show, signal, tick and retry
… and retry executions
…ility meters and the changelog
…egration tests run in CI
… in the capstone and on every database
…he scanner, the capstone and on every database
… Postgres outbox round-trip harness
…MPENSATION_FAILED, dead-letter it and name the steps it left uncompensated
…esume-attempts times FAILED and dead-letter it, and let database faults escape the tick
…and correlation id, and keep the error message at debug level
…ow by depth, so a nested call no longer clears the outer call's mark
…ompensation held back, so the parent does not stay WAITING on a child it already cancelled
# Conflicts: # CHANGELOG.md # README.md # composer.json # docs/README.md # docs/book.md # docs/index.md # docs/modules.md # samples/lumen/tests/Integration/OutboxPostgresIntegrationTestCase.php
… run every lane of the CI matrix IntegrationDatabase now delegates to Firefly\Testing\Integration\IntegrationDsn instead of parsing FIREFLY_* variables by hand, iterates IntegrationDsn::lanes() (the four servers plus a sqlite file) and skips with IntegrationDsn::skipReason(), so each CI integration job runs its own lane. The two-worker interleaving test runs on the server lanes only, and sets SQL Server's LOCK_TIMEOUT unprepared, since a prepared SET is undone when its statement ends.
…a save on SQL Server no longer waits on another execution's open checkpoint The multi-row upsert ran as a MERGE that SQL Server can execute as a scan of the whole attributes table, and under READ COMMITTED that scan blocked on the rows another worker's uncommitted save held. save() now updates each kept key and inserts the new ones by primary key, touching only the execution's own rows on every server.
…ation lane, and add orchestration to the database support matrix
… so no test inherits another's session settings
…exactly-one-loser check fails
…at shortens it, since the runner's driver manager pools sessions
Merged
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.
Adds
firefly/orchestration: sagas, TCC and durable workflows for LaraFly, modeled on jafly'sfireflyframework-orchestrationand at parity with PyFly'stransactionalmodule.What ships
#[Saga]and#[SagaStep(dependsOn, compensate, retry, backoffMs, timeoutMs, idempotencyKey, …)].COMPENSATION_FAILEDand is dead-lettered.SagaBuilderDSL, saga composition with data flow, argument injection (#[Input],#[FromStep],#[Header],#[Variable],#[CorrelationId]),#[StepEvent], completion and error callbacks, and#[ScheduledSaga].#[TccParticipant]s with try/confirm/cancel methods, per-phase timeouts and retries, and#[FromTry]. A TRY that times out is cancelled. TCC executions can be composed.firefly:orchestration:tick, which also runs as a#[Scheduled]task under theDistributedLockport.firefly.orchestration.workflow.max-resume-attempts, so it cannot hold up the tick.firefly.orchestration.persistence.provider=memory|cache|database.memory|database) with retry.firefly/eda, and executions can be started by event-type triggers.orchestrationactuator endpoint and health component, plus metrics and spans throughfirefly/observability.php artisan firefly:orchestration:{list,show,signal,dlq,dlq:retry,tick}.Notes
origin/main(wave W1). The integration tests useIntegrationDsnand its lanes, so they run in the new CI matrix.MERGE, which blocked on other workers' uncommitted rows. It now writes by exact primary key.Verification
composer check