Skip to content

compute: turn the interactive runtime on in test configurations - #38393

Open
antiguru wants to merge 3 commits into
mh/interactive-07-peeksfrom
mh/interactive-08-enable
Open

compute: turn the interactive runtime on in test configurations#38393
antiguru wants to merge 3 commits into
mh/interactive-07-peeksfrom
mh/interactive-08-enable

Conversation

@antiguru

@antiguru antiguru commented Aug 21, 2026

Copy link
Copy Markdown
Member

Last of eight PRs splitting #37770. Stacks on #38392. Tracked by CPU-216.

enable_compute_interactive_runtime moves out of UNINTERESTING_SYSTEM_PARAMETERS, where #38391 parked it, and becomes a variable system parameter defaulting to on. That is what makes every preceding piece reachable: sqllogictest, testdrive, and the mzcompose suites provision replicas with two runtimes. Parallel-workload's FlipFlagsAction is unpinned to both values at the same time. Production keeps the dyncfg's own default, off.

The clusterd mzcompose service grows the second runtime's port and --interactive-compute-timely-config, and the local driver runner takes INTERACTIVE_COMPUTE=1 for the same. Four clusterd-test-driver specs cover the runtime boundary: an index read, a query dataflow that binds before its index is published, a read through an index that re-exports another's arrangement and so aliases its publication point, and a query dataflow that binds to such a re-export before it renders, the one case where the re-export publishes through an import instead. The driver gains two things the binding-first specs need. create-dataflow takes until=, and the specs set until = as_of + 1, without which the dataflow is not single-time and the multiplexer routes it to maintenance. create-dataflow ... defer registers a dataflow's exports without submitting it and submit-dataflow submits it later, so a spec can create and schedule the interactive dataflow before the index it imports exists. Its import then binds to an unbacked publication point that the later maintenance render adopts, which is the ordering the registry exists for and which a race could otherwise only reach by accident.

read_at_max_timestamp.slt covers reads at Timestamp::MAX, the one single-time shape whose until is empty and so the one that is_peek_dataflow admits while !until.is_empty() would have rejected. Such a read is answerable only against a collection that has sealed, since no finite upper passes MAX, so the file reads off constant-backed indexes, whose dataflows have no inputs and drop their capability after emitting once. Both shapes are covered: a fast-path index peek, and a join that cannot take the fast path and so builds a peek dataflow importing two shared indexes. The reads double as the assertion that those indexes sealed, since a peek finding a live frontier would never return. Passes with the flag defaulted either way.

relations.slt gains the publisher operators, and pins the flag itself rather than inheriting the environment default. A variable system parameter can be flipped by CI_SYSTEM_PARAMETERS=random, which would otherwise make the golden mismatch about half the time in randomized runs. The flag is read when a replica is provisioned, and the file creates its own cluster after reset-server, so setting it beforehand is enough.

introspection-sources.td raises a coarse arrangement-size bound from 16 KiB to 32 KiB, since publication doubles the reported size of a one-record index.

singlereplica_attribution_sources.slt asserted a materialized view's timely dataflow id, which counted the peek dataflows the replica rendered before it. Those now render on the interactive runtime, so the assertion is reduced to the id-to-collection pairing.

The ReadIsolationUnderHydration parallel-benchmark scenario from #38542 A/Bs the flag, measuring peek latency with the feature on against off while hydration saturates the maintenance workers.

@antiguru
antiguru force-pushed the mh/interactive-08-enable branch 2 times, most recently from 7cc7c1e to edb0ed3 Compare August 21, 2026 11:50
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from edb0ed3 to 33f6773 Compare August 21, 2026 12:28
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from 33f6773 to 2f0fd74 Compare August 21, 2026 13:24
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from 2f0fd74 to 69cfb34 Compare August 21, 2026 13:42
@antiguru
antiguru requested a review from DAlperin August 21, 2026 13:47
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from 69cfb34 to 51bbf8a Compare August 21, 2026 14:31
pull Bot pushed a commit to Arstman/materialize that referenced this pull request Aug 21, 2026
…nt sharing (MaterializeInc#38396)

Replaces MaterializeInc#37881, whose head branch lives on a fork and so cannot be the
base of a stacked PR in this repository. Same commits, same tree, on an
upstream branch instead. This is the root of the stack MaterializeInc#38386 through
MaterializeInc#38393, which splits MaterializeInc#37770.

### Motivation

Cross-runtime arrangement sharing (the two-runtime read-isolation work,
MaterializeInc#37770) needs batches readable from a thread other than the one
maintaining the trace. Differential's default spines reference-count
batches with `Rc`, which is worker-local.

### Description

Introduce `mz_row_spine::ArcBatch`, a local newtype around `Arc<B>` that
carries differential's batch traits (the orphan rule forbids the blanket
impl on a bare `Arc<B>`), and switch the production spines and their
builders — `RowRowSpine`, `RowValSpine`, `RowSpine`, `ValRowSpine`,
`ColValSpine`, `ColKeySpine` — from `Rc`/`RcBuilder` to
`ArcBatch`/`ArcBuilder`. An `Arc`-backed batch whose contents are `Send
+ Sync` can be read across threads, which `Rc` cannot do. Only the batch
handle becomes atomic; the batch contents are unchanged, so the cost is
a marginally more expensive refcount.

Also adds generic `ArcOrdVal`/`ArcOrdKeySpine` aliases for callers
outside `mz_compute`, adapts batch-size logging
(`log_arrangement_size_inner`) to reach through the newtype to the inner
`Arc`, and switches the storage sink trace to the `Arc`-backed spine.

Builds against released differential-dataflow 0.25 with no fork or
`[patch.crates-io]`.

### Verification

`cargo check --workspace` passes with no `Cargo.lock` churn.
`relations.slt`'s golden is rewritten because the spine type name
appears in operator names.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from 51bbf8a to 4f02fc3 Compare August 21, 2026 17:54
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from 4f02fc3 to 099cda1 Compare August 28, 2026 14:06
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from 099cda1 to be74eb0 Compare September 3, 2026 08:49
@linear-code

linear-code Bot commented Sep 3, 2026

Copy link
Copy Markdown

CPU-215

@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from be74eb0 to 4daa449 Compare September 3, 2026 16:22
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from 4daa449 to ba882e6 Compare September 4, 2026 17:22
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from ba882e6 to 0d948f9 Compare September 4, 2026 17:39
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from 0d948f9 to fc3dd5a Compare September 4, 2026 19:37
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from fc3dd5a to 7e51333 Compare September 5, 2026 08:34
@antiguru

antiguru commented Sep 5, 2026

Copy link
Copy Markdown
Member Author

Confirmed and fixed in 7e51333. create-dataflow takes an until= argument, threaded through to DataflowBuilder::until, and the spec sets until=1, so is_peek_dataflow holds and the multiplexer routes the dataflow to interactive.

The same commit fixes the relations.slt golden that failed SLT 1 on the previous push: the publisher operators are named PublishShared(<id> oks), not PublishShared.

An assertion that distinguishes the two runtimes is still missing; the interactive runtime's introspection is unreachable (CPU-222), so there is nothing to read yet.

Posted by Claude Code.

@def-

def- commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

QA LLM Review

1. MEDIUM -- two-runtime query-dataflow spec cannot reach the unbacked publication point it documents

test/clusterd-test-driver/scripts/two_runtime_query_dataflow.spec:44

The scenario the spec is built around, the interactive import binding to an unbacked publication point that schedule id=2001 later adopts, does not happen as written: create-dataflow name=maint-index renders the maintenance dataflow immediately and publishes and adopts the point right there, before the interactive dataflow is even submitted. The reader-first branch of ArrangementSharingRegistry::get_or_create is therefore reached only by an unsynchronized race between the two runtimes' worker threads, and normally not at all, so a regression that made publish install a fresh slot instead of adopting a reader-created one in place would leave this spec green.

Details

handle_create_dataflow calls build_compute_dataflow unconditionally (src/compute/src/compute_state.rs:964); its own comment at compute_state.rs:851 says "Every dataflow builds immediately, in command arrival order". render::export_index publishes during that build (src/compute/src/render.rs:917), and publish is get_or_create + adopt + notify (src/compute/src/sharing.rs:143). Schedule only drops the suspension token (compute_state.rs:985); it releases the publisher operator's first activation, it neither creates nor adopts the point.

The driver sends commands without waiting for an ack (src/clusterd-test-driver/src/driver.rs:136) and the two runtimes drain their streams on independent worker threads, so which side calls get_or_create first is a race. Since create-dataflow name=maint-index goes out first and maintenance is idle, maintenance normally wins. The comments at lines 17-21, 41-43, 59-61, 71-72 and 77-78 all assert the opposite ordering.

The script cannot simply be reordered: import index=2001 requires the index to be registered already, which only a successful create-dataflow submit does (src/clusterd-test-driver/src/script.rs:847). Reaching reader-first deterministically needs a driver command that registers an index's shape without submitting its dataflow. Short of that, the comments should describe what actually runs: the point is created and adopted at create-dataflow time with an empty chain, and what schedule id=2001 releases is the publisher's first activation, which fills the importer queue and wakes the import.

@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from 81d228a to 872ae4f Compare September 5, 2026 09:18
@antiguru

antiguru commented Sep 5, 2026

Copy link
Copy Markdown
Member Author

Confirmed: create-dataflow rendered and published at submit time, so the reader-first order the spec described was a race maintenance normally won. Fixed in 872ae4f by giving the driver the command the finding says it needs.

create-dataflow ... defer registers the dataflow's exports without submitting it, and submit-dataflow name=<name> submits the recorded spec later. The spec now registers the maintenance index with defer, creates and schedules the interactive dataflow, and only then submits and schedules the index. The import therefore binds to an unbacked point deterministically, and publish adopting that point in place is what the peek's answer depends on. Comments rewritten to describe that sequence.

Posted by Claude Code.

@antiguru
antiguru requested review from a team as code owners September 5, 2026 11:47
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from 872ae4f to 67d7101 Compare September 5, 2026 11:47
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch 2 times, most recently from 3fd0fd7 to 53fa56a Compare September 5, 2026 19:00
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from 53fa56a to e7707d8 Compare September 7, 2026 09:36
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from e7707d8 to d196fa0 Compare September 7, 2026 11:39
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from d196fa0 to 6e98212 Compare September 7, 2026 17:10
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from 6e98212 to 4b255fe Compare September 7, 2026 18:19
antiguru and others added 3 commits September 7, 2026 20:38
`enable_compute_interactive_runtime` becomes a variable system parameter
defaulting to on, which is what makes every preceding piece of this work
reachable: sqllogictest, testdrive, and the mzcompose suites now provision
replicas with two runtimes, so peeks and bounded transient dataflows route to the
interactive runtime and maintenance publishes its indexes for it to read.
Production keeps the dyncfg's own default, which is off.

The clusterd mzcompose service grows the second runtime's port and
`--interactive-compute-timely-config`, mirroring what the controller passes in a
real deployment, and the local driver runner takes `INTERACTIVE_COMPUTE=1` for
the same. Four clusterd-test-driver specs cover the runtime boundary: an index
read, a query dataflow that binds before its index is published, a read through
an index that re-exports another's arrangement and so aliases its publication
point, and a query dataflow that binds to such a re-export before it renders,
which is the one case where the re-export has to publish through an import. The
`ReadIsolationUnderHydration` parallel-benchmark scenario A/Bs the flag,
measuring peek latency with the feature on against off while hydration
saturates the maintenance workers.

Three goldens move. `relations.slt` gains the publisher operators, which are real
operators the maintenance runtime now installs on every published index.
`introspection-sources.td` raises a coarse arrangement-size bound from 16 KiB to
32 KiB, because publication raises the reported size of a one-record index past
the old bound. Whether that overhead is constant per arrangement or scales with
size is not established and wants re-measuring, so the comment records the
measurement without claiming a mechanism. `singlereplica_attribution_sources.slt`
asserted a materialized view's timely dataflow id, which counted the peek
dataflows rendered before it. Those now render on the interactive runtime, so the
assertion is reduced to the id-to-collection pairing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDm7opomJLxbNUEP3r9BLk
A query dataflow that imports a maintenance index and exports it under a
transient id with the same key finds the imported shared arrangement at its
export, which the interactive runtime now publishes as an alias of the index's
publication point. The spec peeks the transient id, which only resolves if the
alias reaches the shared arrangement.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDm7opomJLxbNUEP3r9BLk
The publisher sink showed up in `relations.slt` as an operator and a channel per
published index, and doubled the reported size of a one-record index in
`introspection-sources.td`. The trace wrapper adds neither, so both files return
to their expectations on main, and `relations.slt` no longer pins the runtime
flag.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDm7opomJLxbNUEP3r9BLk
@antiguru
antiguru force-pushed the mh/interactive-08-enable branch from 4b255fe to 0141e18 Compare September 7, 2026 18:43
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