From 0b454f367374e8cb97927627dacd0f1b216fe5ad Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Wed, 13 May 2026 19:41:44 +0300 Subject: introduce Accumulator interface in statsengine to separate ingestion from snapshot-building MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define statsengine.Accumulator (Ingest + Reset) to represent the event-accumulation responsibility separately from runtime.SnapshotSource (Snapshot), which handles the read side. This reduces the SRP violation in Engine: callers that only push events now hold an Accumulator; callers that only read statistics hold a SnapshotSource. - Add Accumulator interface and compile-time assertion in statsengine/engine.go - Add EventIngester type alias (= statsengine.Accumulator) in runtime/runtime.go with a compile-time assertion, so callers in the runtime layer can reference the ingestion contract without importing statsengine directly - Split tuiRuntime.engine field into accumulator + snapSource so the event-loop callback holds Accumulator and wireRuntimeBindings passes SnapshotSource to SetDashboardSnapshotSource — making each consumer's dependency explicit - Simplify resetDashboardSnapshotSource in tui.go to cast for interface{ Reset() } independently of Snapshot(), removing the combined ad-hoc interface check Co-Authored-By: Claude Sonnet 4.6 --- internal/runtime/runtime.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'internal/runtime/runtime.go') diff --git a/internal/runtime/runtime.go b/internal/runtime/runtime.go index e8e278e..5a3c9a9 100644 --- a/internal/runtime/runtime.go +++ b/internal/runtime/runtime.go @@ -40,10 +40,20 @@ type EventSink interface { // behind this interface so the dashboard can retrieve live snapshots. // Snapshot returns (nil, nil) when the engine is nil. A non-nil error // indicates that snapshot construction failed and the result must be discarded. +// This is the read side of the stats engine; the write side is +// statsengine.Accumulator. type SnapshotSource interface { Snapshot() (*statsengine.Snapshot, error) } +// EventIngester is the write-only, event-feeding side of the stats engine, +// as needed by the trace event loop. It is an alias for the statsengine.Accumulator +// contract so callers in the runtime layer can reference a single type without +// importing statsengine directly. Callers that only push events should hold an +// EventIngester; callers that only read statistics should hold a SnapshotSource. +// *statsengine.Engine satisfies both interfaces. +type EventIngester = statsengine.Accumulator + // Snapshotter is the read-only subset of the trie contract used by consumers // that only need to poll the version and retrieve snapshot data. It mirrors the // Snapshotter interface in internal/tui/flamegraph but lives here so the core @@ -208,9 +218,11 @@ var ( // *probemanager.Manager must satisfy the probe-control surface exposed to the TUI. _ ProbeManager = (*probemanager.Manager)(nil) - // *statsengine.Engine must satisfy the snapshot-source contract used by the - // dashboard and the TUI runtime. + // *statsengine.Engine must satisfy both the snapshot-source contract (read + // side) and the event-ingestion contract (write side). These interfaces + // represent the two distinct responsibilities of the engine. _ SnapshotSource = (*statsengine.Engine)(nil) + _ EventIngester = (*statsengine.Engine)(nil) // *streamrow.RingBuffer must satisfy the full event-sink contract (read + // write sides), which is a superset of StreamSource. -- cgit v1.2.3