Lock COW branch requests during mutations#14
Closed
adamziel wants to merge 4 commits into
Closed
Conversation
a10ea7f to
e23f198
Compare
Contributor
|
This PR was auto-closed when its stacked base branch ( Replacement PR with the same change rebased onto |
JanJakes
added a commit
that referenced
this pull request
May 6, 2026
## What it does Adds request-side locking for the COW materialized backend. ForkPress-served WordPress requests now take a shared `flock` on `.forkpress/cow/operations.lock`, while branch create/reset/delete and Git apply continue to take the same lock exclusively. This replaces #14, which was closed automatically when the stacked base branch for #13 was deleted after merging. ## Rationale The COW mutation paths already had an exclusive operation lock, but normal WordPress requests did not participate. That meant a reset, delete, or Git apply could publish or remove a materialized branch tree while a ForkPress-served request was still reading or writing that tree. The lock is advisory and scoped to ForkPress traffic. Direct editor/shell writes to `./main` or another branch are still ordinary filesystem writes and do not automatically honor it. ## Implementation `runtime/router_cow.php` now parses the request path before branch lookup, keeps Git smart HTTP on its existing exclusive lock path, and acquires a shared operation lock before serving normal branch traffic. The lock is released through a shutdown callback so PHP and static file responses both keep it for the lifetime of the request. Added `tests/test_cow_router_lock.php`, which holds the operation lock exclusively, spawns a router request, and verifies the branch PHP does not run until the exclusive lock is released. ## Testing instructions ```bash php -l runtime/router_cow.php php -l tests/test_cow_router_lock.php php -d "extension=$(pwd)/ext/branchfs.so" tests/test_cow_router_lock.php FORKPRESS_RUNTIME_BUNDLE=/dev/null cargo test -p forkpress make test-all cargo build --release --target x86_64-unknown-linux-musl -p forkpress tests/test_cow_strategy_e2e.sh target/x86_64-unknown-linux-musl/release/forkpress ``` Co-authored-by: Adam Zieliński <adam@adamziel.com>
JanJakes
pushed a commit
that referenced
this pull request
May 6, 2026
## What it does Adds `forkpress storage compact` for macOS APFS sparsebundle-backed COW sites and expands `forkpress storage status` with branch/storage roots, lock paths, branch counts, and interrupted-operation leftovers. This is stacked on #14. ## Rationale Sparsebundle-backed sites need a single ForkPress-managed way to stop the site, detach storage, reclaim free image bands, and explain what is still attached or left behind. Direct `hdiutil`/`rm -rf` workflows are too easy to get wrong while a server or branch mutation is active. ## Implementation `storage compact` stops this site's server unless `--keep-server` is passed, detaches sparsebundle storage, runs `hdiutil compact`, and leaves storage detached until `forkpress serve` or `forkpress storage mount`. The COW lifecycle now uses: - `operations.lock` for branch/storage mutations and request exclusion. - `lifecycle.lock` so background server startup and detach/compact cannot race. - A locked server registry so read/filter/write operations cannot clobber a concurrently registered server. The COW E2E now checks lifecycle diagnostics and exercises `storage compact`; macOS CI runs that path with `FORKPRESS_FORCE_MACOS_APFS_SPARSEBUNDLE=1`. ## Testing instructions ```bash FORKPRESS_RUNTIME_BUNDLE=/dev/null cargo test -p forkpress make test-all cargo build --release --target x86_64-unknown-linux-musl -p forkpress tests/test_cow_strategy_e2e.sh target/x86_64-unknown-linux-musl/release/forkpress ```
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.
What it does
Adds request-side locking for the COW materialized backend. ForkPress-served WordPress requests now take a shared
flockon.forkpress/cow/operations.lock, while branch create/reset/delete and Git apply continue to take the same lock exclusively.This PR is stacked on #13.
Rationale
The COW mutation paths already had an exclusive operation lock, but normal WordPress requests did not participate. That meant a reset, delete, or Git apply could publish or remove a materialized branch tree while a ForkPress-served request was still reading or writing that tree.
The lock is advisory and scoped to ForkPress traffic. Direct editor/shell writes to
./mainor./marketingare still ordinary filesystem writes and do not automatically honor it.Implementation
runtime/router_cow.phpnow parses the request path before branch lookup, keeps Git smart HTTP on its existing exclusive lock path, and acquires a shared operation lock before serving normal branch traffic. The lock is released through a shutdown callback so PHP and static file responses both keep it for the lifetime of the request.Added
tests/test_cow_router_lock.php, which holds the operation lock exclusively, spawns a router request, and verifies the branch PHP does not run until the exclusive lock is released.Testing instructions