Skip to content

Scoped feature flags 2/3: durable persistence and introspection (inert)#37080

Merged
antiguru merged 1 commit into
MaterializeInc:mainfrom
antiguru:claude/scoped-flags-2-persistence
Jun 18, 2026
Merged

Scoped feature flags 2/3: durable persistence and introspection (inert)#37080
antiguru merged 1 commit into
MaterializeInc:mainfrom
antiguru:claude/scoped-flags-2-persistence

Conversation

@antiguru

@antiguru antiguru commented Jun 16, 2026

Copy link
Copy Markdown
Member

Second of a three-PR stack splitting #36959: 1/3 #37079 (merged) → 2/3 (this)
→ 3/3 #36959
. Design: doc/developer/design/20260609_scoped_feature_flags.md
(#36947).

Adds the durable storage and introspection for scoped overrides, inert until the
resolution layer (3/3) wires it.

Description

  • Two durable catalog collections, cluster_system_configurations and
    replica_system_configurations, keyed by object id, surfaced as builtin
    materialized views mz_internal.mz_cluster_system_parameters /
    mz_replica_system_parameters over mz_catalog_raw (no new builtin tables,
    per the ongoing MV migration). CATALOG_VERSION 86 with a no-op migration.
  • CatalogState::scoped_system_parameters is the in-memory working copy used for
    resolution, maintained from the durable state with a value-matched retraction
    in apply (order-independent updates); a durable
    Op::UpdateScopedSystemParameters reconciles the persisted cache to a complete
    desired state.
  • Nothing writes the durable collections or the working copy here, so the
    introspection views stay empty and resolution falls back to the
    environment-wide value everywhere — no behavior change until 3/3.

Verification

Catalog migration round-trip and golden-encoding tests (full mz-catalog suite),
regenerated sqllogictest catalog enumerations, and ScopedParameters unit tests.

@DAlperin DAlperin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks

Comment thread src/adapter/src/config.rs Outdated
Comment thread src/catalog/src/builtin/mz_internal.rs Outdated
Comment thread src/catalog/src/builtin/mz_internal.rs Outdated
@antiguru antiguru force-pushed the claude/scoped-flags-2-persistence branch from ba7c8fb to 37dc4cd Compare June 17, 2026 09:59
Comment thread src/catalog/src/builtin/mz_internal.rs Outdated
@antiguru antiguru force-pushed the claude/scoped-flags-2-persistence branch 2 times, most recently from 8916620 to 98a035d Compare June 17, 2026 12:00

@aljoscha aljoscha left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see the one inline comment about builtins please

Comment thread src/catalog/src/builtin/mz_internal.rs Outdated
antiguru added a commit that referenced this pull request Jun 17, 2026
…plumbing (#37079)

### Motivation

First of a three-PR stack splitting #36959 (scoped feature flags) for
review:
**1/3 (this) → 2/3 #37080 → 3/3 #36959**. Design:
doc/developer/design/20260609_scoped_feature_flags.md (#36947).

This PR is the additive foundation: it introduces the vocabulary the
later PRs
build on, with no behavior change on its own.

### Description

* `ParameterScope` (`Environment` / `Cluster` / `Replica`), declared on
system
vars and dyncfg `Config`s and carried through to the synced system vars.
The
declaration is the single source of truth for which contexts get
evaluated.
* The size-family taxonomy: `ReplicaAllocation::family` plus a size-map
`family`
  field, with a `cc` / `legacy` fallback for sizes that don't set one.
* The compute controller's per-replica dyncfg override layer
(`update_replica_dyncfg_overrides` + per-replica command
specialization),
  inert until the adapter wires it in 3/3.

Nothing consumes the scope or the override layer yet, so this is a
no-op.

### Verification

`test_replica_allocation_family` covers the size→family fallback; the
rest is
exercised by the later PRs in the stack.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@antiguru antiguru force-pushed the claude/scoped-flags-2-persistence branch from 98a035d to 32fe560 Compare June 17, 2026 12:47

@aljoscha aljoscha left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the second commit only (catalog: persist scoped system parameters and surface in introspection).

Overall this is clean and closely mirrors the existing durable-collection plumbing; the inert-foundation framing is clear and the commit message is excellent. A few things, grouped by severity (details inline).

Blocking

  • CI is red (slt-1): test/sqllogictest/catalog_server_explain.slt is out of date — it's missing the EXPLAIN MATERIALIZED VIEW entries for the two new MVs (the commit bumped the row counts but didn't add the per-MV blocks). Regenerate with bin/mzcompose --find sqllogictest run catalog-server-explain --rewrite.

Strong suggestions

  • Don't name the vendor ("LaunchDarkly") in user-facing surfaces — the value column comments and the new mz_internal.md prose. It leaks an implementation detail and goes stale if the sync source ever changes; describe it generically.
  • The two introspection MVs wrap the kind filter in a subquery citing database-issues/8495, but that issue is join-specific and these MVs have no join. The join-less catalog MVs (mz_databases, mz_schemas) just use a plain WHERE. Suggest matching them.

Nits (inline)

  • A couple of rustdoc comments narrate design/abstractions that belong in the design doc (consistent with the earlier note on config.rs).
  • The two apply_*_system_configuration_update fns are byte-identical save the id type — a small generic helper would remove the duplication.
  • Redundant liveness check in the reconcile loops; inconsistent visibility on the inert accessors.
  • The reconcile diff/prune and the value-matched retraction are the only non-trivial logic here and are currently untested (inert). A focused unit test would land cleanly now rather than waiting for 3/3.

Comment thread src/catalog/src/builtin/mz_internal.rs Outdated
Comment thread src/catalog/src/builtin/mz_internal.rs Outdated
Comment thread src/adapter/src/catalog/apply.rs Outdated
Comment thread src/catalog/src/durable/objects.rs Outdated
Comment thread src/adapter/src/catalog/transact.rs Outdated
Comment thread src/adapter/src/catalog/state.rs Outdated
@antiguru antiguru force-pushed the claude/scoped-flags-2-persistence branch from 32fe560 to ef3cfe1 Compare June 17, 2026 16:28

@aljoscha aljoscha left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed the updated second commit (ef3cfe1632). Thanks for the quick turnaround — all six points are addressed cleanly:

  • ✅ Vendor name removed from the value column comments and the mz_internal.md prose (and "table" → "view" there too).
  • ✅ Both MVs dropped the subquery + the database-issues/8495 comment and now use a plain WHERE data->>'kind' = '...', matching mz_databases/mz_schemas.
  • ✅ The two apply_* fns collapsed into one generic apply_scoped_system_configuration_update<Id: Ord> helper — nice, and the value-matched-retraction rationale moved into its doc.
  • objects.rs docs: dropped the fragile "step 2/3" references and corrected "on startup" → "maintained from it on every catalog update".
  • ✅ Redundant || !live_*.contains(...) checks removed, with a clarifying comment on why a missing entry already covers dropped objects.
  • ✅ Accessor visibility made consistent (scoped_system_parameters() is now pub, no stray #[allow(dead_code)]).

Still blocking (unchanged): CI slt-1 is still red on the same error — test/sqllogictest/catalog_server_explain.slt is missing the EXPLAIN MATERIALIZED VIEW entries for the two new MVs:

Missing EXPLAIN queries (2):
+ EXPLAIN MATERIALIZED VIEW "mz_internal"."mz_cluster_system_parameters";
+ EXPLAIN MATERIALIZED VIEW "mz_internal"."mz_replica_system_parameters";

The commit regenerated mz_internal.slt / the index-accounting slt and bumped the row counts in catalog_server_explain.slt, but the per-MV EXPLAIN blocks still need to be added. Regenerate with:

bin/mzcompose --find sqllogictest run catalog-server-explain --rewrite

Once that lands and slt-1 is green, this LGTM from my side.

@antiguru antiguru force-pushed the claude/scoped-flags-2-persistence branch from ef3cfe1 to e012691 Compare June 18, 2026 08:49

@aljoscha aljoscha left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two doc-comment nits from a closer re-read (the introspection views themselves look correct — verified parse_catalog_id handles both id types, the kind discriminator matches, and the absence of .with_key is required since the optimizer can't prove the composite key). Both nits are docs that narrate the 3/3 resolution layer rather than the local contract.

Comment thread src/adapter/src/config.rs Outdated
/// Returns a copy of `self` with the cluster and replica overrides from
/// `other` merged in, replacing any existing entry for the same object.
///
/// Create-time resolution uses this to add freshly-evaluated new objects to

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this second paragraph narrates the 3/3 resolution layer ("create-time resolution", "periodic full-state reconcile") that doesn't exist yet in this commit — the same kind of leaking-abstraction the comment thread above flagged. merge itself is just a two-map extend. I'd trim to the local contract, e.g.: "Returns a copy of self with other's entries merged in, replacing any existing entry for the same object. Expresses no removals." The caller-side rationale can live where the caller lands.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trimmed to the local contract: "Returns a copy of self with other's entries merged in, replacing any existing entry for the same object. Expresses no removals." Caller-side rationale will live with the caller in 3/3.

Comment thread src/adapter/src/catalog/state.rs Outdated
/// Returns the cluster-coherent scoped optimizer-feature overrides for
/// `cluster_id` from the in-memory scoped-parameter working copy.
///
/// These are layered on top of the cluster's manual `CREATE CLUSTER ...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this precedence model (cluster-scoped LD rule beats a manual FEATURES pin beats env-wide) is implemented in the 3/3 resolution layer, not here — and it re-introduces the vendor name we just took out of the user-facing surfaces. This accessor is just a lookup + From. Suggest trimming the doc to the contract (returns the cluster's scoped optimizer-feature overrides, empty if none) and keeping the precedence/layering reasoning where the layering actually happens (or in the design doc).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trimmed to the contract (returns the cluster's scoped optimizer-feature overrides, empty if none) and dropped the precedence/vendor prose — that layering lives in 3/3 / the design doc.

@aljoscha aljoscha self-requested a review June 18, 2026 09:00

@aljoscha aljoscha left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a couple more comments before, and would be good to resolve these. But otherwise good to merge!

Durable storage and introspection for scoped (per-cluster and per-replica)
feature overrides, inert until the resolution layer wires it.

* Two durable catalog collections, `cluster_system_configurations` and
  `replica_system_configurations`, keyed by object id, plus their builtin
  introspection tables `mz_internal.mz_cluster_system_parameters` /
  `mz_replica_system_parameters`. CATALOG_VERSION 86 with a no-op migration.
* `CatalogState::scoped_system_parameters` is the in-memory mirror, with a
  value-matched retraction in `apply` so updates are order-independent, and a
  durable `Op::UpdateScopedSystemParameters` that reconciles the persisted cache
  to a complete desired state.
* The working copy is never populated here, so introspection stays empty and
  resolution falls back to the environment-wide value everywhere — no behavior
  change until the resolution layer lands.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@antiguru antiguru force-pushed the claude/scoped-flags-2-persistence branch from e012691 to 8d17f87 Compare June 18, 2026 09:22
@antiguru

Copy link
Copy Markdown
Member Author

Thanks for the reviews!

@antiguru antiguru merged commit 3953456 into MaterializeInc:main Jun 18, 2026
124 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants