Skip to content

Maintain original activity leases while PHP callbacks run inline - #202

Merged
rmcdaniel merged 7 commits into
mainfrom
fix/878-activity-lease-renewal
Oct 21, 2026
Merged

rmcdaniel merged 7 commits into
mainfrom
fix/878-activity-lease-renewal

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

Keep an inline activity alive under its original grant

Part of Workflow #878. This adds automatic maintenance to the earlier bounded Client primitive; an endpoint alone does not fix an ordinary blocking activity.

Current candidate e13d84b95c142cb6feaa962255bde3e30923c86e / whole tree 5f6f292de897b56e9f202b488610eb190be1a2e7 adds the real TLS and rotating-authentication control below to qualified cec79c1b. Production source, dependencies and metadata are unchanged. It incorporates main 3de24db and preserves its tracing portal. Fresh whole-head CI and Sonar are required independently.

Behavior

  • Ordinary callbacks remain inline: injected services, existing application connections and captured memory retain their identity. A separate fresh PHP CLI process renews only the original activity grant and Worker presence, with busy slots and the original parent PID. It does not dispatch activity code.
  • Private bounded IPC carries worker-role credentials and claim metadata, never business payload/history or command-line secrets. Custom HTTP clients/dynamic authentication use an explicit fresh-process Client bootstrap, preserving their configuration instead of silently replacing TLS/proxy/authentication behavior.
  • UTC6 original namespace/queue/task/run/execution/attempt/owner, monotonic budgets, immutable business deadlines and required session TTL are fenced. Real user heartbeat receipts can advance only their recorded progress interval; runtime pings cannot fabricate progress or heartbeat history. Duplicate/stale/foreign replies never restore refused authority.
  • Initial confirmation precedes external argument loading and callback dispatch. Completion/failure is checked again after external uploads. Captured Client clones share the current execution binding; independent Fibers do not share claims. Explicitly forked children cannot use or terminate their parent's maintenance channel.
  • Parent death/pipe closure stops maintenance; every normal/error exit joins the helper. Lost authority fences both completion and failure, including caught heartbeat refusal. It does not claim physical interruption of an inline callback or reversal of external effects.

Actual qualification

  • The preceding Worker implementation runs the unchanged blocking-callback control once in the parent but retains zero completions instead of one after the three-second fixture lease. That counterfactual is an actual failure, not a missing-component/import check.
  • Final PHP 8.3.35 SDK suite: 2,632 cases, 13,155 assertions, 56 existing environment-dependent skips (2,576 passed), 111.003 seconds. All fifty new authority/real-HTTP controls execute. The real-HTTP cases cover inline PID/captured state, repeated renewal without user progress, original business/progress expiry, real application heartbeat relay, changed attempt fencing, caught heartbeat refusal, captured Client publication, custom bootstrap headers and original-owner SIGKILL followed by actual helper disappearance/no further renewal.
  • Full production PHPStan, the dependency-boundary check and strict Composer validation pass. No dependency or package-version change. Earlier endpoint-only 282-case qualification remains its own evidence.
  • The initial prototype's session JSON-key-order issue is corrected with canonical key comparison. Initial HTTP fixture signature/timestamp/setup and double-closed-pipe cleanup failures are retained; they are not attributed to the product or counted as successful originals.

Reviewed analyzer follow-through

The seventeen findings on the preceding candidate were reviewed individually. Identity capture, original deadlines, renewal acknowledgement, helper progress ordering and IPC send/read/validation now have cohesive methods. A dedicated maintenance exception distinguishes helper setup/communication failure. Worker presence configuration is grouped without changing registered/unregistered behavior, the unused request-path argument is removed, and cluster discovery reuses its path constant. No deadline, message-size, timeout, refusal or callback assertion changes.

Exact final PHP 8.3.35 source again passes 2,632 cases / 13,155 assertions / 56 existing skips (2,576 passed), including 72 focused cases / 232 assertions. PHPStan, strict Composer validation and the dependency boundary pass. The initial cleanup missed the direct constructor in the owner-death fixture; its failed ready assertion is retained and the fixture is updated for the grouped presence argument before these final passes. The first PHPStan invocation hit its runner's 128 MiB limit; its complete 512 MiB run passes. No source error is inferred from that resource failure.

One individual require suggestion (AaFeHafTgdQwD3TIDTFQ) is marked FALSE-POSITIVE, not fixed: the custom bootstrap is an executable factory that must return a fresh configured Client. require_once can return boolean true for an already included file and break that contract. The CLI autoloader does use require_once. Fresh Sonar workflow 39596692472 and app analysis now pass. The public issue API explicitly shows 16 CLOSED/FIXED, one RESOLVED/FALSE-POSITIVE and zero OPEN/CONFIRMED, rather than inferring resolution from the badge. No rule, threshold or profile is changed. Normal supported PHP/Laravel/Symfony, corpus, package, documentation and integration CI 39596692454 is terminal SUCCESS. Entire cleanup-phase tools/dependencies/raw are removed at 12:04:11 UTC, with borrowed images preserved.

Actual private-CA and dynamic-authentication boundary

The added local TLS control generates one synthetic private certificate and first proves that an ordinary Client rejects it before any HTTP request reaches the fixture. A custom Guzzle Client with that trust file is then recreated by the documented bootstrap in the independent helper. While its original callback blocks for 4.2 seconds against a three-second lease, the worker credential changes on disk. Actual renewal requests use both the original and rotated credentials, and exactly one completion is retained. TLS verification remains enabled throughout.

The focused real-transport test passes 1 / 17; the complete maintenance file passes 12 / 121, and production PHPStan and TLS fixture lint pass. These are overlapping selections. The first fixture expected the lower-level TransportException, but the public Client wraps it in ServerException; that unsuccessful fixture run is retained and the final test asserts the real public wrapper and underlying certificate failure. The first tool launch inherited an application entrypoint and stopped before tests; its corrected standalone tool does not start an application stack.

Compatibility decision: do not serialize custom HTTP handles or flatten dynamic authentication into static credentials. The explicit bootstrap must recreate them for the same runtime URI, namespace and protocol. A runtime advertising maintenance is checked before claim; missing custom bootstrap remains an actionable configuration refusal. Runtimes without affirmative capability retain their original path. The test follow-through does not change production source, dependencies, protocol or authority.

Merged source checkpoint

All applicable normal checks on e13d84b9 pass, including the supported PHP/Laravel/Symfony matrix, real integration selections, package/corpus/docs, repository policy and Sonar. Protected merge acce3db8bf6b835b73bc653905588bea49041781 has exactly the qualified tree 5f6f292de897b56e9f202b488610eb190be1a2e7. The completed remote PR branch is absent.

Fresh-main CI 39622133587, portal, Sonar and boundary are independently queued. This is merged source, not a published-package or complete #878 acceptance. Actual installed six-minute and killed-worker cohorts remain open. No Server/native/shared/frozen/schema edit, resource hold, threshold or profile adjustment.

@rmcdaniel rmcdaniel changed the title Renew original activity runtime leases with bounded worker requests Maintain original activity leases while PHP callbacks run inline Oct 21, 2026
@sonarqubecloud

Copy link
Copy Markdown

@rmcdaniel
rmcdaniel marked this pull request as ready for review October 21, 2026 15:02
@rmcdaniel
rmcdaniel merged commit acce3db into main Oct 21, 2026
38 checks passed
@rmcdaniel
rmcdaniel deleted the fix/878-activity-lease-renewal branch October 21, 2026 15:02
@rmcdaniel

rmcdaniel commented Oct 21, 2026 •

Copy link
Copy Markdown
Member Author

PHP SDK 3.2.0 is published from merged dfaae75a94b1d855379863799ce2c9a53f900f97 / whole 4359e5b4d8df378af47e2da29f2ef2a2f08fe8cf, identical to qualified #204. Packagist reports that exact source. A fresh ordinary Composer install, with no source override or path repository, passes the existing package/quickstart checks and actual registration identity durable-workflow-php/3.2.0.

Portal run 39638685098 passes build/deploy. The live deployment audit reports the exact merged source, the homepage identifies PHP SDK 3.2 and its onboarding command selects durable-workflow/sdk:^3.2.

The earlier release-metadata original remains failed at its four recorded identity checks; it is not replaced by this result. Actual six-minute/no-progress lease maintenance plus killed-worker recovery remain unfinished under workflow#878. Server 2.10.1's separate critical PHP image publication still pins Core 2.9.0 and does not advertise the new lease capability. Package publication does not close the whole activity-lease issue.

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