Skip to content

Self-update lease: a blocking upgrader sub-phase longer than the takeover window is still seizable (holder-set expiry) #92

Description

@BenKalsky

Raised by Codex on #91 (round 4, P1) and capped there by the owner (2026-09-09): plan 2 ships the phase-boundary renewals and the in-phase heartbeat on the upgrader's filters (SA#80), and this issue records what those cannot cover.

The gap. Aura_Worker_Magic_Link::take_claim() stores fence|timestamp, and a seizer treats a claim older than ITS window (ten minutes, passed by every caller) as dead. The holder can move the timestamp — refresh_claim() between phases, and from heartbeat_during()'s upgrader filter callbacks inside a phase — but PHP is single-threaded: nothing runs while one blocking call (download_url(), unzip_file(), copy_dir(), ZipArchive::extractTo()) is in progress. A single such call that lasts longer than the window leaves the lease seizable, and a successor can start replacing the same directory while the first request is still inside its call.

Why it is a residual, not a defect being shipped. The window exists precisely to reclaim dead holders, and max_execution_time bounds a request well under ten minutes on every host in the fleet; SiteAgent's own zip is ~1 MB. #78 round 25 (SA#80's origin) accepted the same residual for the self-update's install(). After plan 2 the outlived request also STOPS on the first check that fails (no restore, no verdict, no rollback over the successor's files — #91 round 3), so the cost of the race is bounded to two installs of the same build, never a rollback over a newer one.

The fix, when it is worth it. A lease with a holder-set expiry: the value becomes fence|expires_at, the holder sets expires_at = now + min( max_execution_time, HARD_CAP ) before each blocking phase, and a seizer takes over only past expires_at — the claim cannot expire during an operation the holder has declared. This changes the claim primitive that the connect (#434) and the site claim share (take_claim / refresh_claim / release_claim / the regex-matched $wpdb stubs), so it is its own change with its own review, not a task in plan 2.

Refs: #80, #91 discussion r3971802169, plan docs/superpowers/plans/2026-09-09-siteagent-2.17-agent-code.md Task 4.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions