Conversation
beinan
force-pushed
the
feat/registry-etcd
branch
from
September 29, 2026 20:11
a57247c to
df05f52
Compare
… a mirrored migration path The store registries (rollout, generic, datagen) are a name -> uri directory every worker consults on a cache miss and writes on every create/delete. As a Lance table each read is a manifest fetch from object storage and each write is two contended commits; even after lance-format#274 keeps it compact, a create costs seconds and throttling turns it into failures. Introduce a StoreRegistry trait (&self, so the RwLock every request went through goes away) with three impls: LanceRegistry (today's table), EtcdRegistry (one key per store under <ETCD_PREFIX>/registry/<kind>/, put-if-absent backfill), and MirroredRegistry (read one, write both, mirror best-effort). REGISTRY_BACKEND / REGISTRY_MIRROR select them; defaults keep Lance with no mirror, so this change is behaviour-neutral until the flags are set. The master seeds the mirror from the primary at startup and heals it every maintenance round, and exposes GET /registry/diff and POST /registry/backfill for verifying a migration step. ETCD_* flags move to core (EtcdConfig) so the server can share them; the master's etcd prefix is unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
beinan
force-pushed
the
feat/registry-etcd
branch
from
October 2, 2026 03:48
df05f52 to
0d61086
Compare
This branch has not been deployed
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.
Design:
docs/src/design/registry-etcd.md(in this PR).Problem
The store registries (
_registry.rollout.lance,.generic,.datagen) are aname -> uridirectory that every worker consults on an LRU miss (get_or_open_*) and writes on every create/delete. As a Lance table:checkout_latest= one manifest fetch from object storage (0.7 s on ADLS today, 1.5 s+ under throttling), on the hot path of every API call that misses the worker cache;POST /rolloutsaveraged 47 s and 500'd 79 times in 15 h when ADLS throttled mid-way;The master already runs etcd for its task queue and locks, and the cluster exposes it to the namespace. A directory of ~11k
{uri, created_at}entries is exactly what etcd is for.Change
core
StoreRegistrytrait:contains / get / list / upsert / remove / insert_missing, all&self. Today'sRwLock<RolloutRegistry>existed only because Lance handles mustcheckout_latest; dropping it removes a serialisation point every worker request went through.LanceRegistry(wrapsRolloutRegistry; keeps fix(master): compact and version-prune the store registries alongside _stats #274's maintenance vialance_table()),EtcdRegistry(one key per store under<ETCD_PREFIX>/registry/<kind>/<name>,upsertis a plainputthat preservescreated_at,insert_missingis per-entry put-if-absent txns),MirroredRegistry(read primary, write both, mirror best-effort with a warning).backfill_registry(from, to)anddiff_registries(a, b).EtcdConfig(theETCD_*flags, moved out of the master so the server can share them) andRegistryConfig(REGISTRY_BACKEND=lance|etcd,REGISTRY_MIRROR=lance|etcd) with anopen_registry()factory. Defaults are Lance with no mirror, so this PR is behaviour-neutral until the flags are set.server: the three registries become
Arc<dyn StoreRegistry>;create_*,get_or_open_*,unregister_*,list_*are unchanged in shape. Config gains the two flag groups.master: same swap;
TaskStoreconnects throughEtcdConfig(prefix unchanged, keys unchanged); seeds the mirror from the primary at startup and heals it every maintenance round;GET /api/v1/registry/diff?kind=andPOST /api/v1/registry/backfill?kind=for verifying a migration step; #274's Lance maintenance is a no-op on an etcd backend.Migration (env-only, each step revertable)
REGISTRY_BACKEND=lance REGISTRY_MIRROR=etcd: reads unchanged, writes mirrored, master backfills. Checkdiffis empty.REGISTRY_BACKEND=etcd REGISTRY_MIRROR=lance: reads from etcd; Lance kept current for rollback.REGISTRY_BACKEND=etcd: done. Lance tables stay on disk as cold backup;discovery.rscan rebuild etcd from the data directory regardless.Verification
registry_etcdtests (etcd-backed): upsert/get/contains/remove incl.created_atpreservation on retried create;list+insert_missingwith duplicates; prefix names (avsab) do not collide.mirrored_registry_keeps_both_backends_in_step: the step-1 configuration end to end — pre-existing Lance rows,diffshows them,backfillcopies them, mirrored writes and removes land in both,diffis empty.-D warnings, fmt clean.Not in scope:
_stats(needs range queries; stays in Lance), MemWAL shard manifests.🤖 Generated with Claude Code
Rebase and review follow-up (2026-10-02)
Rebased onto upstream
b85db02, including #292 and #284. Resolved the registry/merge configuration overlap without duplicate etcd CLI arguments, preserved lazy merge-only connection behavior, and retained the recovery coordinator, repair/rescan routes, and serial fan-out. Updated registry call sites added since the original branch.Local validation on the rebased code: 88 master tests, 92 worker tests, and 14 core registry tests passed, with the etcd-backed cases enabled against isolated local etcd. Clippy passed for core/master/server/merge with all targets and warnings denied; formatting and diff checks passed. CI has restarted on the rebased head.
Migration review remains unresolved: master backfill/diff does not cover datagen even though worker backend selection switches it; insert-only mirror healing cannot repair missed deletions; and the name-only diff can report agreement despite different URIs. Two local diagnostic probes reproduced the latter two failures. These probes are not part of the committed suite. Do not treat the existing migration/rollback description or passing happy-path tests as evidence that these cases are safe. This rebase does not enable or deploy the registry backend.