diff --git a/differential-dataflow/CHANGELOG.md b/differential-dataflow/CHANGELOG.md index 256bb80d2..47419adf6 100644 --- a/differential-dataflow/CHANGELOG.md +++ b/differential-dataflow/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- `Agent` trait over the shared reader an arranging operator returns, implemented by `TraceAgent`, and `arrange_core_with_agent`, `reduce_with_tactic_and_agent`, and `arrange_from_upsert_with_agent`, which return a caller-chosen agent. `Agent::new` receives the trace by value, so an agent can keep state the trace shares before `TraceAgent` takes ownership of it. + ## [0.25.1](https://github.com/TimelyDataflow/differential-dataflow/compare/differential-dataflow-v0.25.0...differential-dataflow-v0.25.1) - 2026-07-15 ### Other diff --git a/differential-dataflow/src/operators/arrange/agent.rs b/differential-dataflow/src/operators/arrange/agent.rs index 8850feecc..8ce484c09 100644 --- a/differential-dataflow/src/operators/arrange/agent.rs +++ b/differential-dataflow/src/operators/arrange/agent.rs @@ -68,6 +68,28 @@ impl TraceReader for TraceAgent { fn map_spans)>(&self, f: F) { self.trace.borrow().trace.map_spans(f) } } +/// A shared reader of a trace, constructed by the operator that maintains the trace. +/// +/// The arranging operators (`arrange_core_with_agent`, `reduce_with_tactic_and_agent`, +/// `arrange_from_upsert_with_agent`) build their trace, hand it to `Agent::new`, keep the writer, +/// and return the agent in the resulting `Arranged`. The operator also reads through its own copy of +/// the agent, so an implementation must honour the `TraceReader` contract of the trace it shares. +pub trait Agent: TraceReader + Sized { + /// The trace the agent shares. + type Trace: Trace