Skip to content

adapter: notify SystemVars callbacks at the catalog commit boundary (… - #38046

Open
mtabebe wants to merge 1 commit into
MaterializeInc:mainfrom
mtabebe:ma/sql-525-systemvars-commit-boundary
Open

adapter: notify SystemVars callbacks at the catalog commit boundary (…#38046
mtabebe wants to merge 1 commit into
MaterializeInc:mainfrom
mtabebe:ma/sql-525-systemvars-commit-boundary

Conversation

@mtabebe

@mtabebe mtabebe commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

SQL-525)

Problem:
SystemVars::register_callback lets something mirror a system var's value into out-of-band state. Today the only user is the connection limit in ConnectionCounter. However, these callbacks fired straight from SystemVars::set/reset/set_default, which run inside transact_inner on the speculative cloned candidate state. So if a transaction applied a system-config op and then aborted, the mirror was left ahead of the catalog. transact_incremental_dry_run, which never commits anything notified for changes that get thrown away by design.

Solution:
Move the notification to the commit boundary. SystemVars::notify_all_callbacks fires from Catalog::transact right after the durable commit and state swap, and only when the transaction actually contained a system-config op. Since the callbacks are idempotent reads of the SystemVars they're handed, firing all of them on any system-config commit is cheap, and it saves us from threading a set of changed var names back out of transact_inner.

With that in place, set/reset/set_default no longer notify at all. Callbacks now only run from register_callback (the once-at-registration guarantee) and from the commit-boundary notify_all_callbacks, so whatever they mirror can only ever reflect committed catalog state.

Drop the dead SystemVars::reset_all.

Testing:
Two regression tests

  • a transact_incremental_dry_run carrying a max_connections op must not notify, even though the base-state clone does carry the callbacks;
  • a transact whose second op fails after the first already applied must not notify, and must leave the committed value alone.

Plus an mzcompose workflow against a real environmentd, test-connection-limit-tracks-committed-vars in test/cluster: it holds one counted connection open and walks the enforced connection limit through every op that can change a system var (ALTER SYSTEM SET, RESET, RESET ALL) plus a rejected SET, requiring a new connection to be refused or allowed exactly as the committed value dictates. Neither sqllogictest nor testdrive can express this, since neither can assert that establishing a connection fails.

…SQL-525)

Problem:
`SystemVars::register_callback` lets something mirror a system var's value into
out-of-band state. Today the only user is the connection limit in
`ConnectionCounter`. However, these callbacks fired straight from
`SystemVars::set`/`reset`/`set_default`, which run inside `transact_inner` on
the speculative cloned candidate state. So if a transaction applied a
system-config op and then aborted, the mirror was left ahead of the catalog.
`transact_incremental_dry_run`, which never commits anything notified
for changes that get thrown away by design.

Solution:
Move the notification to the commit boundary. `SystemVars::notify_all_callbacks`
fires from `Catalog::transact` right after the durable commit and state swap,
and only when the transaction actually contained a system-config op. Since the
callbacks are idempotent reads of the `SystemVars` they're handed, firing all of
them on any system-config commit is cheap, and it saves us from threading a set
of changed var names back out of `transact_inner`.

With that in place, `set`/`reset`/`set_default` no longer notify at all.
Callbacks now only run from `register_callback` (the once-at-registration
guarantee) and from the commit-boundary `notify_all_callbacks`, so whatever they
mirror can only ever reflect committed catalog state.

Drop the dead `SystemVars::reset_all`.

Testing:
Two regression tests
- a `transact_incremental_dry_run` carrying a `max_connections` op must not
  notify, even though the base-state clone does carry the callbacks;
- a `transact` whose second op fails after the first already applied must not
  notify, and must leave the committed value alone.

An mzcompose workflow against a real environmentd,
`test-connection-limit-tracks-committed-vars` it holds one counted connection
open and walks the enforced connection limit through every op that can change
a system var (`ALTER SYSTEM SET`, `RESET`, `RESET ALL`) plus a rejected `SET`,
requiring a new connection to be refused or allowed exactly as the committed
value dictates. Neither sqllogictest nor testdrive can express this,
since neither can assert that establishing a connection fails.
@mtabebe
mtabebe force-pushed the ma/sql-525-systemvars-commit-boundary branch from 4e84297 to 6b6be85 Compare August 4, 2026 15:20
@mtabebe
mtabebe marked this pull request as ready for review August 4, 2026 16:41
@mtabebe
mtabebe requested a review from a team as a code owner August 4, 2026 16:41
self.shared_transient_revision
.store(self.transient_revision, atomic::Ordering::SeqCst);
self.state = new_state;

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.

I don't know the details of this is wired right now, but could we instead move this to the catalog implications framework, so that this also works when another envd does the change and we listen to it? For the future multi-envd world.

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.

2 participants