diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-12 23:09:00 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-12 23:09:00 +0300 |
| commit | fa439f7f6f145b4a47aeb107619e9efbd07bc9d8 (patch) | |
| tree | cb8590c4a4c808c30bc94e867b98599a54ab8f90 | |
| parent | 15338e6d4253fc8f4871a68ddcc41c6e3ce58220 (diff) | |
split LiveTrieSource into Snapshotter and Configurator (ISP)
Applies the Interface Segregation Principle to LiveTrieSource in both
internal/runtime and internal/tui/flamegraph. The monolithic interface is
replaced by two focused sub-interfaces — Snapshotter (read-only: Version,
SnapshotJSON, SnapshotTree) and Configurator (mutating: Fields, CountField,
Reconfigure, SetCountField, Reset) — which LiveTrieSource then embeds so all
existing consumers continue to compile unchanged. The buildSnapshotMsg helper
is narrowed to Snapshotter since it only reads snapshot data, preventing
accidental mutation from the background goroutine.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| -rw-r--r-- | internal/runtime/runtime.go | 43 | ||||
| -rw-r--r-- | internal/tui/flamegraph/model.go | 44 |
2 files changed, 71 insertions, 16 deletions
diff --git a/internal/runtime/runtime.go b/internal/runtime/runtime.go index a9e959a..5e6f2a4 100644 --- a/internal/runtime/runtime.go +++ b/internal/runtime/runtime.go @@ -42,19 +42,46 @@ type SnapshotSource interface { Snapshot() *statsengine.Snapshot } -// LiveTrieSource is the minimal flamegraph-trie contract needed by the tracing -// engine and the flamegraph TUI model. It mirrors the interface defined in -// internal/tui/flamegraph but lives here so the core package need not import -// that TUI sub-package. Both interfaces are satisfied by *flamegraph.LiveTrie. -type LiveTrieSource interface { +// 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 +// package need not import that TUI sub-package. +// *flamegraph.LiveTrie satisfies this interface. +type Snapshotter interface { + // Version returns the monotonically-increasing snapshot generation counter. + Version() uint64 + // SnapshotJSON serialises the current trie to JSON for external consumers. + SnapshotJSON() ([]byte, uint64) + // SnapshotTree returns a ready-to-render snapshot tree without a JSON round-trip. + SnapshotTree() (*flamegraph.SnapshotNode, uint64) +} + +// Configurator is the write/mutating subset of the trie contract used by +// consumers that need to change field layout, metric, or reset the baseline. +// It mirrors the Configurator interface in internal/tui/flamegraph but lives +// here so the core package need not import that TUI sub-package. +// *flamegraph.LiveTrie satisfies this interface. +type Configurator interface { + // Fields returns the current ordered list of grouping fields. Fields() []string + // CountField returns the active aggregation metric name. CountField() string + // Reconfigure replaces the grouping fields and resets accumulated data. Reconfigure([]string) error + // SetCountField changes the active aggregation metric and starts a fresh baseline. SetCountField(string) error + // Reset clears all accumulated data, starting a new baseline. Reset() - Version() uint64 - SnapshotJSON() ([]byte, uint64) - SnapshotTree() (*flamegraph.SnapshotNode, uint64) +} + +// LiveTrieSource is the full flamegraph-trie contract needed by the tracing +// engine and the flamegraph TUI model. It embeds Snapshotter (read-only +// snapshot access) and Configurator (mutating operations) so each can be used +// independently where a narrower interface suffices. Both interfaces are +// satisfied by *flamegraph.LiveTrie. +type LiveTrieSource interface { + Snapshotter + Configurator } // ProbeManager exposes runtime probe controls to the TUI probes modal. diff --git a/internal/tui/flamegraph/model.go b/internal/tui/flamegraph/model.go index 8d2e577..68ce7fd 100644 --- a/internal/tui/flamegraph/model.go +++ b/internal/tui/flamegraph/model.go @@ -73,18 +73,44 @@ const flameKeyDebugEnabled = false // JSON+layout work or a 1-second animation chain. const driveWindow = 250 * time.Millisecond -// LiveTrieSource is the minimal trie contract needed by the flamegraph TUI model. -// SnapshotJSON is retained for tests and external callers; SnapshotTree is the -// fast path used by the model's background refresh. -type LiveTrieSource interface { +// Snapshotter is the read-only subset of the trie contract: version polling and +// snapshot retrieval. buildSnapshotMsg and background refresh goroutines use +// only this narrower interface so they cannot accidentally mutate trie state. +type Snapshotter interface { + // Version returns the monotonically-increasing snapshot generation counter. + // Callers use it to avoid re-rendering an unchanged trie. + Version() uint64 + // SnapshotJSON serialises the current trie to JSON for external consumers + // (retained for tests and CLI callers; not used by the TUI render path). + SnapshotJSON() ([]byte, uint64) + // SnapshotTree returns a ready-to-render snapshot tree without a + // JSON round-trip. It is the fast path used by the background refresh. + SnapshotTree() (*snapshotNode, uint64) +} + +// Configurator is the write/mutating subset of the trie contract: field layout, +// metric selection, and baseline reset. The flamegraph controls (cycleFieldOrder, +// toggleCountField, resetBaseline) call only these methods. +type Configurator interface { + // Fields returns the current ordered list of grouping fields (e.g. ["comm","path"]). Fields() []string + // CountField returns the active aggregation metric name (e.g. "count", "bytes"). CountField() string + // Reconfigure replaces the grouping fields and resets accumulated data so a + // new baseline begins with the new field order. Reconfigure([]string) error + // SetCountField changes the active aggregation metric and starts a fresh baseline. SetCountField(string) error + // Reset clears all accumulated data so the next ingested event starts a new baseline. Reset() - Version() uint64 - SnapshotJSON() ([]byte, uint64) - SnapshotTree() (*snapshotNode, uint64) +} + +// LiveTrieSource is the full trie contract needed by the flamegraph TUI model. +// It embeds Snapshotter (read-only snapshot access) and Configurator (mutating +// operations) so each can be used independently where a narrower interface suffices. +type LiveTrieSource interface { + Snapshotter + Configurator } type zoomState struct { @@ -581,7 +607,9 @@ func (m *Model) RefreshFromLiveTrie() bool { // buildSnapshotMsg performs the CPU-heavy snapshot+layout work on a background // goroutine. It returns a flameSnapshotReadyMsg that the Update loop consumes // to apply the new frame layout without blocking the UI goroutine. -func buildSnapshotMsg(liveTrie LiveTrieSource, width, height int, zoomPath string) tea.Msg { +// Only snapshot reads are needed here, so the parameter is narrowed to +// Snapshotter rather than the full LiveTrieSource. +func buildSnapshotMsg(liveTrie Snapshotter, width, height int, zoomPath string) tea.Msg { tree, ver := liveTrie.SnapshotTree() if tree == nil { return flameSnapshotReadyMsg{version: ver, layoutWidth: width, layoutHeight: height, zoomPath: zoomPath} |
