Expand description
The service’s consumer of after-commit push and upkeep work.
What:
The service’s consumer of after-commit work: pending push and maintenance work items of one repository are
claimed, coalesced, run, settled, and a push that failed leaves a record that the person’s next wrapper command shows.
Why:
A commit must not wait for the network or for upkeep, so the wrapper leaves a record and the resident service does
the work on its own thread (doc/planning/cli-git-resident-service.md, “After-commit work”). The service is the
only pusher of the repositories it serves, so no lock is needed: several pending pushes of one branch become one
push, and a service that died mid-push is noticed by the lease of its claims running out, never by a process id: the
holder renews the lease while it works, so a successor that starts beside a holder that is still running leaves its claims
alone, and one that starts after the holder died takes them back as soon as the lease is over. Other kinds of work
(the standards review) are never claimed here.
In TS you’d write (pseudocode):
for (const group of coalesce(await claimAll(workDir, ['push', 'maintenance']))) settle(group, await handler(group));Structs§
- Drained
- What:
What one drain of a directory hands back: how long until it must be looked at again for a claim another instance holds, and
the changes it asks of the retry plan.
Why:
A drain runs on a worker and cannot change the plan, which the service loop owns; it returns what it did and the loop
applies it (
PushRetries::apply). - GitHandlers
- The handlers that run real Git.
Enums§
- Verdict
- What a handler came to.
Constants§
- CLAIM_
LEASE - How long a claim goes without a renewal before another instance runs its item again; the holder renews it three times in this
span while it works (
service_claim_renewal.rs), so a holder that is slow keeps its claim and one that died loses it after this long. Measured by killing a throwaway service during a claim: the service binary in a fixture repository claimed a push held by the remote’s hook, was killed with SIGKILL 1.5 s after the claim (with its process group), and a new service was started and woken; the push was made again 119.57, 119.56 and 119.55 s after the kill in three runs (2026-11-03), so the cost of a kill is the lease to within half a second. No kill of a commit service appears in the user journal of this host (19 boots), so the kills a person meets were not counted. The renewal thread is independent of the landing (service_claim_renewal.rs), so a landing that stalled for 119.8 s (the longesttotal_msin the service journal) does not stop renewals; a stall of the whole process longer than the 80 s a renewal may be late would. Kept at 120 s as the coordinator’s pick under the owner’s delegation, open to the owner’s veto (doc/planning/cli-git-shipped-limits-audit.md, “Picked for these follow-ups”, batch size and claim lease, option B). - MAX_
TRIES - How many times an item is tried before it is given up on.
- SERVICE_
KINDS - The kinds of work the service runs itself.
Traits§
- Work
Handlers - What runs each kind of work.
Functions§
- drain
- What:
Runs everything pending for one repository: takes back the claims whose holder stopped renewing them, claims every pending
push, maintenance and review item, runs one push per branch and one upkeep per repository, settles the items, and leaves a
notice for each failed or skipped push. Gives how long until a claim another instance still holds runs out its lease, or
nothing when there is none.
Why:
Coalescing keeps a burst of commits to one push; a handler that fails leaves the items in
failed, not in a loop. A claim found in this directory may belong to a live instance (a restarted service starts beside the one it replaces, and the linked worktrees of a bare repository share a directory), so only its lease says it was abandoned; the caller is told when to look again, because nothing else would wake it once the lease is over. This keeps no retry plan: a push that could pass is reported as failed, as for handlers that do not retry. The service’s rounds usedrain_plannedinstead. - drain_
common_ records - What:
Runs the records the releases before one service per worktree left in the common directory of a bare repository, from the
instance of a linked worktree: nothing for a repository with a main worktree, for a main worktree and for a directory with
no
commondir. Why: Those releases kept every worktree’s records in the common directory. A repository with a main worktree has an instance whose own directory that is, and it runs them (the main worktree’s current records live there too), so a linked instance must not. A repository whose worktrees are all linked has no such instance, and its pushes would sit there with no notice. Several linked instances may drain the directory at once, so a claim is taken back only after its lease, which the holder renews while it works. - drain_
common_ records_ planned drain_common_recordsfor a service round:firstis the pause before the first new try of a push that could pass (nothing keeps no plan), and the plans the drain asks for are keyed by the common directory, which the service loop wakes by itself when one is due; that wake drains the common directory as a directory of its own, which has nocommondir.- drain_
common_ records_ with_ lease drain_common_recordswith the lease given, so a test can use a short one.- drain_
planned drainfor a service round: the pushes due again come with the request, and the changes the drain asks of the retry plan are given back with the wait, for the service loop to apply.- drain_
planned_ with drain_plannedwith the lease and the renewal given.- drain_
with_ lease drainwith the lease given, so a test can use a short one.- drain_
with_ renewal drain_with_leasewith the way its claims are kept fresh given, so a control can drive the renewal itself.- is_
acceptable - What: Whether an item is one this service should act on for this repository. Why: Anyone who can write the work directory can write an item, so the fields that become a directory, a reference or a program argument are checked before they are used.
- run_
planned_ round - What:
Runs one round over
directorieswith the retry plan: takes what is due for each directory out of the plan, hands it to that directory’s worker as an owned value, applies the changes the workers ask once they are done, and gives for each directory when to look at it again, whichever is first of its leases and its plan. Why: The plan is owned by the caller and changed here on the caller’s thread only, so the workers share nothing and no lock is taken. A directory whose drain planned a push under another directory (a common directory of a bare repository) is named too, so that its wake is not lost. - run_
round - What:
Runs one round of wakes: holds each wake’s review credential in memory for the round, drains each named repository once,
repositories side by side, and drops the credentials when the round ends. Gives, for each repository that has a claim
another instance holds, how long until that claim’s lease runs out, in the order the repositories were named.
Why:
The credential is held only for the reviews of the round that brought it; a service that restarts before the round
runs has none, and its reviews record the plain “no key” outcome. The service looks at such a repository again when the
time is over, because the holder may have died and nothing else would wake the work. Repositories share nothing, so the
round drains them side by side (
service_round.rs); the credentials are passed to the workers as values in a copy of the handlers made for this round, so nothing is shared mutably and no lock is taken. - run_
round_ on run_roundwith the host’s resources chosen by the caller, so a control states a host of any size.- work_
directory - The work directory of a repository.
Type Aliases§
- Wake
- What a wake message brings: the repository to work on and the review credential that came with it, if any.