Repository navigation
A correctness and reliability release, recommended for everyone running the storage
core (shadow or authoritative mode), above all with Postgres, several nodes, or agents
that can push. It also switches the default bundled git to the v2.56.0 release.
Fixes
- A rejected push update could be recorded in the database (authoritative, two or
more nodes). git hands the updates of a non-atomic push that it rejected for a wrong
old value to the reference-transaction hook. When a reference had moved away and back
on another node, the old value matched the database but not this node's copy: the
client was told[remote rejected] (incorrect old value provided)while the database
kept the update, and the node's copy diverged until the reference was written again.
The whole push is now refused in that case, as for a stale create since 0.4.1. Shadow
mode logs and counts it, and never refuses. - What a refused non-atomic push leaves behind is now documented exactly. git runs a
non-atomic push as two transactions, deletions first. A refused deletion fails the
first and nothing lands; a refused create or update fails the second, after the
deletions git accepted have landed. The client gets
fatal: in 'prepared' phase, update aborted by the reference-transaction hook(SSH)
or a hang-up (smart HTTP), with no status per reference (LIMITATIONS). - Postgres connection churn failed writes under load. The store used database/sql's
defaults (unbounded open connections, 2 idle), so a busy node opened about two new
connections per changeset; with 200 concurrent writers 919 of 2000 changes failed with
connection resets. The pool is now bounded and reused: 0 failures in the same runs.
This is a reliability fix; on a single busy repository the speed gain is small
(2-11% lands/min). - Reference names git can't hold side by side (a directory/file pair such as
refs/heads/aandrefs/heads/a/b). A create that conflicts with an existing name is
refused alone by the update hook, with the reason on the client's terminal; the
database checks again at commit; a node's catch-up no longer stops on a legal history
in which one name of a pair was deleted before the other was created. - Agents could reach reserved or decoy references through a symbolic branch.
Symbolic branches are now judged by their written target on RPC write paths,
first_parent_refand the start point are read exactly, and agents cannot create or
update references under the decoy namespaces.
New
graft storage delete-conflicting-ref REF EXPECTED_TARGET(RPC
DeleteConflictingReference, authoritative mode only) repairs a repository that
already holds such a pair: it deletes one side, only if it still has the expected
value, as an ordinary changeset that every node applies.- Postgres pool settings under
[graft.storage]:database_max_open_conns(32),
database_max_idle_conns(same as max open),database_conn_max_idle_time(5m),
database_conn_max_lifetime(30m). Keep the sum over all nodes below the server's
max_connections, with room for a graceful upgrade, when a node briefly runs two
pools. Setting them with SQLite is a startup error. See CONFIGURATION. - Metric
graft_storage_prepared_step_seconds{kind,step}splits the time under the
repository's write lock into record, local read, pack, commit and durability. - Conformance harness: stock git against gitai in every storage mode, now a CI step.
- Design: DB-first writes (doc/graft/design/dbfirst-writes.md, with a TLA+ model).
A plan to lift the per-repository write bound for server-side writes; nothing of it
is enabled in this release.
Changes
- Default bundled git is the v2.56.0 release (was 2.55.0-rc1). The test suites pass
with it; in the land-path benchmark the median p99 changed by +7.4% (within run-to-run
noise), throughput unchanged (BENCH).
Upgrade
No data migration. With Postgres, check the new pool limits against your server's
max_connections (defaults: 32 per node). The 0.4.1 advice on references over 1024
bytes still applies.