Repository navigation
[fence 6/9] libsql-server: namespace fence admin API and lifecycle interlocks - #46
Closed
tszymczyszyn-shopify wants to merge 4 commits into
Closed
tszymczyszyn-shopify wants to merge 4 commits into
tszymczyszyn-shopify wants to merge 4 commits into
Conversation
This was referenced Oct 5, 2026
tszymczyszyn-shopify
force-pushed
the
namespace-fence/5-admin-api
branch
from
October 13, 2026 19:41
dbfec82 to
c1d0470
Compare
tszymczyszyn-shopify
force-pushed
the
namespace-fence/4-target-lifecycle
branch
from
October 13, 2026 19:41
e3b4ab4 to
5a38436
Compare
Author
|
New in this PR after the rebase onto #53 (summary in #41): the fence's checks run inside |
Serve the fence contract of docs/NAMESPACE_FENCE.md section 4 on the admin listener (new http/admin/fence.rs): - GET /v1/fence/capabilities, always served: protocol version, whether fences are enabled, served commands, states, proxy stable_code support, server build and instance id, and the number of active fences counted from the fence registry. - GET /v1/namespaces/:ns/fence (InspectFence): the durable record, the owning operation's receipts (or ?receipts=all), live admission, drain counters and the live replication log id; read-only, and also served while fence tables exist with the flag off. - One POST route per source and target command, all through NamespaceStore::execute_fence_command, and validation-query, which runs one read-only program under the operation's validation capability with a 10 000-row bound. Command routes answer 404 unless --enable-namespace-fence is on, refuse to run without an admin auth key (admin_auth_required) or on a replica (not_primary), parse bodies strictly (invalid_argument), and refuse restore options on target creation (restore_not_allowed). Responses carry the outcome, replay flag, fence view, receipt and drain counters with the outcome's admin status. Co-authored-by: Tomasz Szymczyszyn <tomasz.szymczyszyn@shopify.com>
Refuse config changes, delete, reset, fork (as source or destination), create over an existing record (with or without a dump URL), linking to a shared schema and schema migration while a namespace's fence denies lifecycle work. A single check reads the fence registry, so it also sees in-memory gates (a closing transition, a target being created, an indeterminate commit) and never loads the namespace. Paths that persist through the metastore are refused again inside its transaction. A fork reads the source's log without a read lease, so it now holds the source's transition lock for its whole run and checks the gate under it: a write or read fence command either completes first and the fork is refused, or waits for the fork. Reset writes nothing to the metastore and is checked under the same lock. The fork destination is checked before anything is stored and again with its namespace entry held; previously a fork onto an existing, unloaded namespace would publish its config in memory and remove its directory. A dump URL is no longer fetched for a create that is refused. Registering a schema migration job checks the schema and every linked namespace, so a link written by a binary that does not know fences cannot lead to a migration step being refused halfway through a job. Co-authored-by: Tomasz Szymczyszyn <tomasz.szymczyszyn@shopify.com>
…tion Undoing an unfinished create or fork discards the name's config and, if it is still marked incomplete, its directory. A name that has fence state (a quarantined target, a fenced namespace, or state that cannot be established) was not made by that creation. The config row was already kept by the fence record's foreign key, but only as an opaque SQLite error, after which the directory was still discarded. Check the fence inside the discard transaction, return the fence's refusal, and keep the directory when the fence refused.
fork holds its source's transition lock while it reserves its destination. With the destination's entry checked only for a loaded namespace, fork(X->Y) and fork(Y->X) on unloaded namespaces each held the other's source entry and waited for it, which also froze every fence command on both namespaces. The reservation refuses a destination that exists as soon as it holds its entry, so the two cannot wait for each other. Pin that with a deterministic test: a hook point parks both forks with their source's transition lock held, then both must be refused. The test times out if the reservation stops checking existence.
tszymczyszyn-shopify
force-pushed
the
namespace-fence/4-target-lifecycle
branch
from
October 13, 2026 20:51
5a38436 to
950c901
Compare
tszymczyszyn-shopify
force-pushed
the
namespace-fence/5-admin-api
branch
from
October 13, 2026 20:51
c1d0470 to
892546d
Compare
Author
|
Closing. This stack is parked; the note at the top of the description explains why. The branch is kept at |
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 the admin fence routes and capability discovery, the first externally reachable surface of the fence. Mutating routes require an admin auth key. While an incompatible fence is active, delete, reset, fork, restore, generic config writes and schema changes are refused with typed errors.
Review focus
Route shapes and authentication preconditions against section 4 of the contract.
Since the rebase onto #53: the fence checks of create and fork run inside
Reservation::acquire, under the entry lock, and undoing an unfinished creation leaves a name with fence state alone. From review: a deterministic test parksfork(X→Y)andfork(Y→X)with their source's transition lock held and requires both to be refused; it times out if the reservation stops refusing existing destinations.Commits
Stack
Part 6 of 9, based on
namespace-fence/4-target-lifecycle. The stack sits on #53 (tszymczyszyn/atomic-namespace-create), which sits on #51: review and land #51 → #53 → #41 → … → #49 bottom-up, restacking after each squash or rebase merge.The first version of these PRs carried #35's fence diff unchanged on
v0.9.30-shopify-patches. On 2026-10-13 the stack was rebased onto #53 (how the conflicts were resolved is summarised in a comment on #41) and gained the commits marked above.