doc: design decoupled coordination - #38696
Conversation
9705b3c to
d1afd3d
Compare
cfbf09d to
9d5e1a9
Compare
|
Commit 9d5e1a9 connects storage-backed catalog read protection to committed delivery. Bounds and maintained requirements have separate durable records, final-state transaction validation rejects incompatibility and regression, and the adapter returns admission errors before its fatal commit boundary. Committed bounds reach storage through implications. Dry runs model collection births and drops without controller effects. This is an intermediate milestone 1 change, not activation. SQL creation still needs to produce initial bounds and logical-input requirements with secured readability, including shared-shard initialization. Recovery and durable-progress publication remain unwired. Validation: formatting, targeted compilation, and the durable admission/reopen and adapter admission/dry-run tests pass. Independent review findings are resolved. Regular PR CI is still pending: https://buildkite.com/materialize/test/builds/134033 |
a13ac74 to
7c30792
Compare
Define catalog authority for maintained lifecycle and separate it from request-scoped query execution. Record the ownership and readability boundaries needed for independent clients, while leaving implementation mechanisms open and full multi-adapter operation outside this deliverable. Include an append-only implementation log for work across sessions.
Make sink export installation an implication of the committed catalog diff, not a sequencer-side lifecycle call. Create exports after source and table inputs, then initialize their default read policies. Existing read holds protect inputs through installation, and SQL success still waits for it. Extend sink compatibility coverage with no-op creation and rename operations. Independent review found no blocking issue. CI Clippy and formatting passed before a documentation push superseded the run. Runtime validation remains pending, and local builds were blocked by missing artifacts and tools. This is an incremental ownership migration. Cluster-side catalog following, MV/index creation implications, and direct committed-update tests remain open.
Separate index reconstruction from bootstrap orchestration so committed catalog implications can reuse it without inheriting bootstrap timestamp selection or installation. Keep cache validation, dependency ordering, and CREATE INDEX behavior unchanged. This is preparatory work, not index lifecycle decoupling. Runtime cache reads and committed index installation remain to be implemented. Validation: adapter cargo check and Rust formatting passed. Independent review found no issues. Full formatting and lint were blocked by local tooling and dependency build failures. Runtime tests and PR CI are pending.
Make index-add implications acquire compatible cached plans or reconstruct from catalog definitions, then install after cluster and storage creation. Retain precommit optimization and success-only session notices, without a sequencer installation closure. Reuse the existing read-hold handover. Expose best-effort expression-cache reads through its task and validate cached dependencies against committed state and available compute imports. Filter session notices for optimizer dependencies dropped during planning. Extend cache-handle tests and add cache-disabled SQL restart coverage for index use, EXPLAIN, notices, and drop cleanup. Same-batch external catalog application remains a test gap until a production subscriber exists. Adapter and cache-test compilation, Rust and Python formatting, and Ruff passed. Full local formatting and lint are blocked by missing tools. Runtime validation is delegated to the draft PR CI and remains pending.
Register materialized view storage collections from committed implications before dependent sinks and indexes acquire read holds. Share descriptor construction with bootstrap to preserve initial visibility and replacement shard ownership. Apply read policies through the deferred batch. Keep compute installation and write enablement in the sequencer for this incremental step. Extend the existing MV test with a dependent index. Adapter cargo check and Rust/Python formatting pass. Independent review found no issue. Full local formatting and lint are blocked by missing tools and a doctest dependency build. Regular PR CI is pending.
Reuse bootstrap MV optimization and notice rendering as a catalog-based planning boundary for compute implications. Preserve cache policy, SQL typing, item versions, and timestamp selection. Compute installation and input read protection remain unchanged. Extend cache-disabled restart coverage to MV results, stored EXPLAIN plans, and continued maintenance after restart. Validation: adapter cargo check and Rust/Python formatting passed. Independent review found no issue. Full formatting and lint are blocked by missing tools and an OpenSSL dependency build. Runtime validation and regular PR CI are pending.
Keep a REFRESH AT CREATION materialized view unexecuted across restart, change its input after creation, and verify reconstruction uses the committed refresh timestamp rather than current input state. Extend the existing cache-disabled restart workflow without a test-only coordinator API. Record the input-protection obstacle to moving runtime MV installation. Broader creator holds can change historical readability and do not cover all access paths exposed by catalog changes. Validation: Python formatting and Ruff passed. Full local formatting and lint are blocked by missing tools and an OpenSSL dependency build. Runtime coverage is pending regular PR CI.
Record explicit catalog bounds as the compaction authority for maintained collections. Define the catalog transaction, application, and recovery boundaries while leaving representation, granularity, and publication cadence to implementation and measurement. Document delegated advancement as an alternative and explain the tradeoff between ongoing catalog publication and owner-backed DDL admission. Preserve the exploration log and append the agreed decision. Documentation checks passed, including preservation of earlier log entries. Full formatting and lint remain blocked by missing tools and the Python doctest OpenSSL dependency build. No runtime behavior changes.
Expand unmaterialized views through their relational name references and raw HIR reads, independently of optimization and available indexes. Stop at persisted collection outputs and logs, preserving exact version IDs. This establishes dependency discovery for logical recovery protection without changing admission, read holds, or runtime installation. Add catalog-boundary tests for eliminated and implicit inputs, shared view subgraphs, index independence, MV boundaries, and collection versions. Adapter library and test compilation pass. Rust formatting passes. Full formatting and lint are blocked by missing tools and an OpenSSL dependency build. Runtime validation remains pending in draft PR CI.
…y tests Strip validation churn from the design's implementation log: pending CI, passed formatting checks, local tooling gaps, and review outcomes are all reconstructible from the PR and buried the findings and decisions. Update the session prompt so future handoffs record only findings, decisions, open questions, and the next step, and note which local checks work. Reduce the logical_collection_inputs tests to the promises that matter: name resolution survives planning-time elimination, raw-HIR reads count, indexes do not affect traversal, and upstream MV outputs are leaves. The dropped version test mutated catalog maps directly, and the replacement-MV case cannot run in the debug catalog because it has no shard metadata for the target.
Focus implementation on observable recovery, lifecycle, and query-client outcomes in environments initialized under the new protection rules. Defer existing-environment conversion without weakening its result preservation contract. Direct implementers to the active milestone and retain rejected alternatives as decision context rather than pending work.
Account for committed compaction permission independently of retention policies and execution holds. Preserve it during initialization, shared shard version changes, and drops, and apply monotonic advances in batches. Recovery uses protected readability rather than policy frontiers, and initialization stops if a fencing compare fails. This is the storage consumer boundary for decoupled coordination. Durable catalog production, maintained admission, and MV recovery wiring remain unimplemented, so SQL-created collections do not yet use these bounds. Five focused storage tests cover persist advancement, recovery, aliases, and drops. Recovery regressions were verified with the fixes removed. Formatting, cheap lint checks, and all-target checks through adapter and compute-client pass locally. Broad validation remains with draft PR CI.
Include logical collection inputs in MV refresh preparation and creation timestamp selection, even when planning or optimization removes their reads. Preserve early holds and acquire missing planner-introduced inputs before installation, rejecting explicit refreshes that those inputs cannot support. Carry query-scoped name references separately from statement dependencies so replacement targets do not constrain input readability. Add SQL coverage for eliminated inputs, automatic timestamps, refresh-at-creation, replacement targets, and implicit SQL-function reads. This prepares catalog-backed recovery protection but does not implement durable bounds or maintained requirements. Admission currently uses held readability. Validation: bin/fmt, cargo check for mz-adapter and mz-sqllogictest with all targets, and selected Cargo, formatting, and Python-doc lint checks passed. SQL execution and broader validation are delegated to draft PR CI.
Accept committed removal of collection metadata during creation without releasing the installed compaction bound. Catalog implications create collections before applying drops, so requiring the removed bound in the committed snapshot rejects valid mixed batches. Keep requiring bounds for collections that remain cataloged and retain shared-shard protection until explicit drop application. Extend the version/drop boundary test to cover create-before-drop and rejection of missing bounds for still-cataloged collections. The regression failed before the fix. Targeted storage-bound tests, cargo check, formatting, and selected repository lint checks passed. Regular PR CI remains pending. This unblocks catalog-bound delivery but does not add its durable producer.
Persist storage-backed compaction bounds separately from maintained logical read requirements. Validate final transaction state before batch extraction and return admission failures before the adapter fatal commit boundary. Deliver committed bounds through catalog implications and preserve collection lifetimes in dry runs and drops. This connects catalog authority to storage enforcement without enabling SQL production of the records. Creation, recovery, and progress publication remain work toward the first protected MV. Add durable reopen and admission coverage, plus adapter coverage for committed updates and staged collection lifetimes.
Keep valid client protection independent of the components enforcing compaction, while query execution remains ephemeral. Record the volatile alternative and its failure tradeoff without prescribing a component, schema, or lease mechanism. Add independent-client recovery evidence to milestone 3 and retain the protected-MV production path as the immediate integration target.
Allow any component to apply committed monotonic permission without exclusive ownership. Keep coordination at authorization, read admission, and reclamation boundaries, with collection identity and all valid read protection preserved. Record concurrent and delayed application as milestone evidence without removing fencing from controllers that still rely on private accounting.
Commit logical MV requirements and collection compaction permission before installation, including fresh builtin collections. Advance requirements from durable output progress and publish compatible bounds in batches, while retaining valid execution and creation holds. Recover using actual protected readability, co-register shared-shard aliases, and preserve leased readability during read-only handover. Retry finite persist since delivery through rate limits and primary changes. Separate DDL conflict tracking from planning-cache freshness so background protection and cadence controls preserve existing SQL behavior. Enable the path at fresh-environment initialization, off by default in production and on in tests. Existing-environment conversion and builtin schema migration remain outside milestone 1. Add a production-path demonstration of optimized-away input protection, actual compaction, historical admission, uncached pending-refresh recovery, and progress-driven history release. Keep catalog consistency comparisons complete by quiescing publication while acquiring their snapshots. Validation: formatting and targeted compilation checks pass. The milestone demonstration passes in draft-PR CI. See the PR for broad check outcomes.
Record the architectural review priorities in the implementer prompt: publication scaling, consistency-check coupling, and remaining ownership dependencies. Keep the design unchanged and retire resolved steering rather than accumulating a permanent checklist.
Keep milestone 1 active beyond the protected-MV checkpoint. Cover source and sink recovery requirements and compute compaction before moving to independent lifecycle execution. Retain catalog-local authorization and its traffic tradeoff without prescribing duplicate records or stronger historical recovery guarantees.
Keep builtin schema migration and protected-environment version upgrades outside the fresh-environment decoupling deliverable, alongside existing environment conversion. Demonstrate the ownership model before tackling those follow-on concerns. Preserve fresh builtin initialization, same-version recovery, and ownership handover within the milestones.
A fresh index has no bound until first publication, and recovery installs at the least readable frontier, capped by permission only where permission is at or above readability. When it is below, nothing durable depends on the gap because durable protection of an index protects its inputs, so the index is replaced and its bound follows through publication. Installation never waits for a catalog write. Record that client requirements on indexes protect the index's inputs, which is what makes this safe under milestone 3. Agree to move the consistency checker's reconstruction behind the existing environmentd diagnostic check and remove the dedicated command, header, and frozen catalog mode. Merge the paused steering items accordingly.
…ication Publish index permission from installed readability, without birth records, installation-time catalog writes, or read-only waits. Preserve feasible saved permission and replace indexes at readability when it is not feasible. Track changed controller frontiers and maintained input requirements. Validate affected durable records using structurally shared projections, and retire sparse bounds from final lifetime changes. Reconstruct independent durable snapshots through the existing diagnostic endpoint off the coordinator thread. Preserve ordinary invariant checks and legacy compatibility without a frozen mode or dedicated snapshot command. Add controlled recovery and publication-cost workflows, held-readability coverage, and bounded-kind counters for committed catalog row payload. Keep experiment dispatch out of the regular pipeline. The large identical-index stress case exposes quadratic notice and dependency work plus repeated uncached planning. Its scope split remains unresolved. Milestone 1 is not declared complete.
Compare 100 and 1,000 generated objects while retaining the shared-view index topology and diagnostics. Keep larger cohorts available explicitly, and defer full-scale performance work beyond this milestone.
…dence Include the generated inventory entries for committed catalog row counters. Record the maintained-lifecycle handoff and keep experiment-only dispatch out of the regular pipeline. The production measurement workflows retain 100/1,000-object defaults and explicit larger-cohort support.
Derive complete MV recovery requirements at the catalog transaction boundary, preserving query references eliminated by optimization and distinguishing replacement targets from reads. Validate surviving birth promises and writer identities against final transaction state. Prepare storage metadata from final catalog membership rather than locally installed collections. Preserve shared-shard aliases and orphan reclamation without authorizing physical finalization. These are prerequisites for independent lifecycle following. Compute installation and controller servicing remain adapter-owned.
217fda5 to
a89eb08
Compare
The controller bundle moves into one independent process whose interface is catalog following, enactment, and publication. It neither serves controller state to adapters nor gates their catalog writes, so it can later dissolve into per-cluster followers. Adapters read through a query client that owns their read requirements, learns storage frontiers from persist and compute frontiers from the fast protocol, and carries durable client protection from the start. Table appends and DDL stay with adapters. Once publication leaves the adapter, adapter DDL and lifecycle publication are two cooperating catalog writers, so that much concurrency is now in scope. Re-cut milestone 2 as independent maintained lifecycle for one adapter and one query client, and milestone 3 as multiplicity and isolation of clients. Order the prompt's steering so each step lands in-process before the process boundary moves.
MV replacement changes the catalog item ID but retains storage collection aliases. Pin collection versions in stored references independently of table schema evolution, and preserve explicit GlobalIds in session-catalog lookups. Downstream recovery requirements then continue to match reconstructed SQL without treating shared shard identities as interchangeable permission.
Motivation
Make the catalog authoritative for maintained storage and compute lifecycle,
independent of the adapter that initiated a change. Query-local execution stays
on a separate fast protocol. The design records the ownership, read-protection,
recovery, and query-ordering boundaries.
Description
Milestone 1 is complete within the agreed 100/1,000-object performance scope.
The implementation, production evidence, and final regular PR CI are verified.
The target is fresh environments and same-version recovery.
Admission accounts for optimized-away inputs and committed permission, not
lagging physical compaction. Pending first refreshes and builtin inputs are protected.
including remap protection, source-export birth floors, and sink input alteration.
Fresh sinks use committed input permission for their automatic cutoff, including
SNAPSHOT = false. Existing pending output remains protected.storage and compute compaction proposals. Controller proposals preserve creation
and execution holds. Committed bounds govern storage and readable compute exports.
or wait for the writer. Recovery respects feasible saved permission and replaces
at actual input readability when the saved bound is stale conservatism. Live
execution holds remain protected.
Durable validation visits affected records and consumers. Sparse index retirement
follows final lifetime changes, without MIN birth records or whole-index scans.
General catalog snapshot and storage-metadata cloning costs remain for measurement.
It is named for that scope, not presented as a maintained-lifecycle executor.
at an aligned prefix off the coordinator thread. Normal invariant checks retain
their behavior. Testdrive requests an explicit reconstruction response and retains
external comparison only for older servers. There is no frozen catalog mode,
dedicated dump-snapshot command, or upper header. Publication cadence is positive.
The adapter stages protection through one operation. Storage creation and emitted
sink-command tests cover execution holds preserving history older than policy
permission, with and without catalog governance.
Protection defaults off in production and on in tests. Existing unprotected
objects are not converted. Sink exports and indexes install through catalog
implications. MV storage registration follows implications, but MV compute
installation still uses a sequencer closure. Controllers still live in the adapter.
Metric sinks require input execution protection, not historical output guarantees.
The restart demo covers actual persist compaction, an optimizer-eliminated input,
uncached pending-refresh recovery, system-catalog inputs, source/remap recovery,
pending sink output, and the fresh no-snapshot sink cutoff. A separate configurable
workflow measures production publication, concurrent DDL latency, catalog traffic,
and retained history at increasing collection counts. The completed runs and their limits are recorded below.
The bounded measurement scope is 100 and 1,000 generated objects, retaining the
shared-view index topology and diagnostics. Full-scale performance work is deferred.
The history consolidates the older WIP implementation while preserving the design
decision and prompt-only changes as distinct patches. Temporary experiment dispatch
is removed from the final tree, but the workflows remain runnable.
Later milestones cover
independent maintained-lifecycle following, independent query clients and durable
client protection, and catalog/query ordering. The permission subscriber is not yet
an independent maintained-lifecycle executor. Existing-environment conversion,
builtin schema migration, and protected-environment version upgrades remain
follow-on work after fresh-environment decoupling.
Milestone 2 prerequisites
Commit
a89eb08fmakes MV requirement completeness a catalog-writer responsibility.Creation without a sequencer-supplied requirement protects all logical query inputs,
including optimized-away reads. Optional selected frontiers are checked against
final-state birth promises. Replacement targets are distinct from query reads, and
retired writer aliases keep completed requirements rather than adopting a new query.
Storage metadata preparation uses final catalog membership, including all collection
versions, rather than installed collections. Shared live aliases prevent shard
retirement, while orphan mappings do not. Preparation does not physically finalize
shards. No new durable records or test-only production interfaces are added.
Commit
8328f7f1preserves user-MV collection versions in stored SQL and insession-catalog GlobalId lookups. Downstream SQL and recovery requirements keep the
same input identities across replacements, including consumers created between
successive replacements. Exact requirement validation is unchanged.
Milestone 2 is not complete. The agreed order is an in-process adapter query client
with durable client protection, the cluster-side lifecycle/query connection split,
cooperating catalog writers, then committed-state MV/metric-sink installation and sink
alteration followed by the controller process move. Adapters retain DDL and table
appends. The lifecycle process only follows the catalog, enacts maintained state,
and publishes protection. No controller-access API or DDL forwarding through it is
planned. Protection record shape and incarnation reclamation are awaiting approval
before implementation. The cooperating-writer mechanism has its own later approval gate.
Validation
Current head
8328f7f1is awaiting regular PR CI inbuild 134383.
The prerequisite head
a89eb08ffailed Testdrive 5 inbuild 134273. Upstream MV
replacement rebound a downstream MV's SQL input to a new GlobalId while its durable
requirement retained the old one, blocking publication. The focused Rust reproduction
failed twice before the version-binding correction and passes with it. The kept
regression covers two replacements, an intervening new consumer, unchanged protected
read identities, successful publication, and both public GlobalId lookup APIs.
On the current source,
bin/fmt,git diff --check,cargo test -p mz-adapter --lib test_materialized_view_, andcargo clippy --all-targets -- -D warningspass. The two targeted tests are thebirth-admission and downstream-replacement regressions. These local results do not
replace pending regular PR acceptance.
The earlier build 134269
failed its two Clippy jobs on eight
unwrap()uses in the new adapter test.Those now have descriptive
expect()messages. The correction is folded into thesingle prerequisite commit, with no production or assertion changes.
Local verification passed:
bin/fmtandgit diff --check.cargo clippy --all-targets -- -D warnings, after reproducing the CI failure.cargo test -p mz-adapter --lib test_materialized_view_birth_admission.The MV test exercises writer-derived requirements, optimized-away inputs, final-state
admission, refresh promises, replacement cutover, and retired-writer aliases against
an in-memory Persist catalog. The three storage preparation tests fail at the original
installed-collection lookup. The MV test fails because its requirement is absent when
writer derivation and its validation are removed. Both pass with their implementations
restored. These are prerequisite boundary proofs, not a maintained-lifecycle subscriber
demo. The milestone 1 acceptance and production evidence below apply to their recorded
heads, not to this prerequisite commit.
The six schema-3 publication jobs passed at
eac2b075a567inbuild 134248.
Final regular CI passed for cleanup head
cbf055e2inbuild 134250.
Its production and test source trees exactly match the evidence head. The PR remains a draft and nightly is
not enabled. The two earlier lint failures were the missing generated inventory
entries for the new payload metrics. Those entries are included, and both lint
jobs pass in the evidence run.
Native targeted coverage includes sparse durable bounds, independent diagnostic
reconstruction, held-readability sink commands, controller compaction, and exact
committed-payload accounting. The latter checks insertions, replacements,
retractions, unchanged records, and rejected/read-only/savepoint writes.
Recovery demonstration
Restart 2 passed in build 134248. It exercises the production path with expression caching
disabled, actual persist batch compaction, and an optimizer-eliminated input.
At the pending-refresh observation:
1789047257958.1789047280000, beyond that refresh.147 updates, versus 81 in the identically revised control.
This is one small-scenario footprint observation, not total disk accounting.
below that timestamp, demonstrating admission by permission rather than lagging
physical compaction.
The assertions recover without a replica, resume the pending MV to return
1while the live input returns
2, recover the system-catalog-input MV, and releaseold input history after completion without dropping the MVs. Ongoing output
advances its requirement. The workflow also covers source/remap and sink recovery,
no-snapshot sink admission, and unpublished/published index recovery.
Read-only following
All four proof jobs passed at
44a20e37inbuild 134190.
Paired values are before/after sibling drop. They measure from observed writer
permission to observed follower frontier, including SQL observation, not true
commit-to-apply time or isolated subscriber CPU.
The writer snapshot requests took 1.36–1.75 seconds. These are individual
observations, not latency distributions. The proof also covers unpublished bounds,
following beside a frozen SQL savepoint, suspended-cluster prewarming, capped
permission, and advancement after restoring cadence. The bootstrap DROP overlaps
startup but does not force an exact bootstrap phase.
Bounded publication measurements
All six jobs in build 134248 completed both sizes, each with three 30-second
observation rounds. Sparse means ten advancing tables plus 90/990 unchanged
governed indexes and a support view. Active means 100/1,000 advancing tables.
Catalog-wide counters include builtin work, not just the generated objects.
Decimal kB = 1,000 bytes. Rate ranges below are the envelope of each round's
outer/inner scrape-time bounds, not confidence intervals. Pair latencies are
successful CREATE/DROP execution latencies, not scheduled-arrival response times.
At 1,000 objects, maintained-requirement payload adds 14.6–16.0 kB/s at 1s cadence
or 1.57–1.60 kB/s at 10s. Other catalog rows add about 4.8 kB/s with the full DDL
load, and zero without DDL. A bound replacement normally contributes two row
updates, not one publication.
All non-observer DDL runs achieved 2 pairs/s with no missed slots. Polling completed
172/180 pairs at 100 objects and 168/180 at 1,000, missing 8 and 12 slots. No DDL
request straddled the observation end. At 100 objects, sparse no-observer p95 was
69.3–79.3 ms versus 100.3–104.6 ms at 1,000. The corresponding active values were
65.0–77.4 ms and 151.9–162.1 ms. This is bounded scaling evidence, not proof of a
complexity class or no regression against a pre-feature baseline.
Findings:
flat. Increasing advancing tables increases it. Baseline catalog cloning still
exists, so flat payload is not a claim of constant total coordinator work.
combined consensus metadata with DDL remains about 32–40 kB/s. This does not
establish a universal cadence ratio. The default cadence is unchanged.
is not an efficiency improvement.
100. The 10,000-identical-index setup failures in build 134190 remain documented:
30–104-second coordinator stalls, quadratic notice/dependency costs, and repeated
uncached optimization. The exact stall attribution was not profiled. Larger-scale
work is deferred by agreement, not hidden by weakening diagnostics.
Packed-row bytes exclude timestamps, diff encoding, compression, and network framing.
Persist state-diff bytes measure encoded consensus metadata, not row payload or all
network/blob traffic. Counter samples can include boundary activity, so dividing
these numerators by in-window DDL count does not yield exact bytes per DDL.
Current-state footprint and sampled history
These are first-round-before to last-round-after metric scrapes for 1,000 objects,
including intervening update phases. They are not total retained disk bytes or
measurements of garbage-collection completion.
Every sampled table had 2,640 referenced batch bytes and two parts at both metric
endpoints. Final sampled retained-update counts were three. INSPECT snapshots and
byte scrapes are sequential, not synchronized. Catalog footprints include setup
and startup history as well as live records, so these are not isolated retention
savings or fleet-wide estimates.
Reproduction
Use disposable CI composition projects, not the development VM:
These workflows reset their project volumes. Sparse controls add
--active-collections 10 --filler-kind indexes. The no-DDL control uses--ddl-rate-hz 0, polling uses--observer poll, and slow cadence uses--publication-interval-ms 10000.Replaces #38694 under the outcome-focused name Decoupled coordination.