Rename fabro_store::RunState to RunProjection

Clarifies that this type is an event-sourced projection of run history,
distinct from fabro_core::ExecutionState which tracks live execution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-04-03 16:37:19 -07:00
parent a667fb7472
commit 103d1bf511
No known key found for this signature in database
8 changed files with 27 additions and 27 deletions

View file

@ -4,7 +4,7 @@ use std::path::Path;
use anyhow::{Context, Result};
#[cfg(test)]
use fabro_store::NodeVisitRef;
use fabro_store::{RunState, SlateRunStore};
use fabro_store::{RunProjection, SlateRunStore};
use fabro_workflow::run_dump::RunDump;
use fabro_workflow::run_lookup::{resolve_run_combined, runs_base};
#[cfg(test)]
@ -79,7 +79,7 @@ pub(crate) async fn export_run(run_store: &SlateRunStore, output_dir: &Path) ->
async fn export_run_to_dir(
run_store: &SlateRunStore,
state: &RunState,
state: &RunProjection,
output_dir: &Path,
) -> Result<usize> {
let dump = RunDump::store_export(run_store, state).await?;

View file

@ -4,7 +4,7 @@ use std::process::Output;
use std::sync::Arc;
use std::time::{Duration, Instant};
use fabro_store::{EventEnvelope, RunState, SlateRunStore, SlateStore};
use fabro_store::{EventEnvelope, RunProjection, SlateRunStore, SlateStore};
use fabro_test::TestContext;
use fabro_types::RunId;
use object_store::local::LocalFileSystem;
@ -492,7 +492,7 @@ fn run_store(run_dir: &Path) -> SlateRunStore {
block_on(store.open_run_reader(&run_id)).expect("run store should exist")
}
pub(crate) fn run_state(run_dir: &Path) -> RunState {
pub(crate) fn run_state(run_dir: &Path) -> RunProjection {
let store = run_store(run_dir);
block_on(store.state()).expect("run store state should exist")
}

View file

@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::Duration;
use fabro_store::{RunState, SlateRunStore, SlateStore};
use fabro_store::{RunProjection, SlateRunStore, SlateStore};
use fabro_types::RunId;
use object_store::local::LocalFileSystem;
pub(super) fn fixture(name: &str) -> PathBuf {
@ -47,7 +47,7 @@ fn run_store(run_dir: &Path) -> SlateRunStore {
block_on(store.open_run_reader(&run_id)).expect("run store should exist")
}
pub(super) fn run_state(run_dir: &Path) -> RunState {
pub(super) fn run_state(run_dir: &Path) -> RunProjection {
let store = run_store(run_dir);
block_on(store.state()).expect("run store state should exist")
}

View file

@ -10,7 +10,7 @@ mod slate;
mod types;
pub use error::{Result, StoreError};
pub use run_state::{NodeState, RunState};
pub use run_state::{NodeState, RunProjection};
pub use runtime::RuntimeState;
pub use slate::{SlateRunStore, SlateStore};
pub use types::{CatalogRecord, EventEnvelope, EventPayload, NodeVisitRef, RunSummary};

View file

@ -14,7 +14,7 @@ use fabro_types::{
};
#[derive(Debug, Clone, Default)]
pub struct RunState {
pub struct RunProjection {
pub run: Option<RunRecord>,
pub graph_source: Option<String>,
pub start: Option<StartRecord>,
@ -50,10 +50,10 @@ pub struct NodeState {
#[derive(Debug, Clone, Default)]
pub(crate) struct EventProjectionCache {
pub last_seq: u32,
pub state: RunState,
pub state: RunProjection,
}
impl RunState {
impl RunProjection {
pub(crate) fn apply_events(events: &[EventEnvelope]) -> Result<Self> {
let mut state = Self::default();
for event in events {
@ -547,7 +547,7 @@ fn conclusion_from_failed(
fn stage_visit(
node_id: &str,
properties: &serde_json::Map<String, Value>,
state: &RunState,
state: &RunProjection,
) -> Option<u32> {
properties
.get("node_visits")

View file

@ -15,7 +15,7 @@ use tokio_stream::wrappers::UnboundedReceiverStream;
use crate::keys;
use crate::run_state::EventProjectionCache;
use crate::{
CatalogRecord, EventEnvelope, EventPayload, NodeVisitRef, Result, RunState, RunSummary,
CatalogRecord, EventEnvelope, EventPayload, NodeVisitRef, Result, RunProjection, RunSummary,
StoreError,
};
use fabro_types::RunId;
@ -147,11 +147,11 @@ impl SlateRunStore {
R: DbRead + Sync,
{
let events = list_events_from(db, 1).await?;
let state = RunState::apply_events(&events)?;
let state = RunProjection::apply_events(&events)?;
Ok(state.build_summary(catalog))
}
async fn projected_state(&self) -> Result<RunState> {
async fn projected_state(&self) -> Result<RunProjection> {
let next_seq = {
let cache = self.inner.projection_cache.lock().await;
cache.last_seq.saturating_add(1)
@ -271,7 +271,7 @@ impl SlateRunStore {
self.inner.db.list_all_assets().await
}
pub async fn state(&self) -> Result<RunState> {
pub async fn state(&self) -> Result<RunProjection> {
self.projected_state().await
}
}

View file

@ -1,5 +1,5 @@
use fabro_config::run::MergeStrategy;
use fabro_store::{RunState, SlateRunStore};
use fabro_store::{RunProjection, SlateRunStore};
use fabro_types::PullRequestRecord;
use tracing::{debug, info};
@ -204,7 +204,7 @@ fn parse_dot_summary(dot: &str) -> (String, usize, usize) {
/// Nodes are sorted alphabetically so `plan` is preferred over `planning`.
/// For repeated visits, earlier visits sort first to match the prior on-disk
/// directory scan behavior.
fn read_plan_text(state: &RunState) -> Option<String> {
fn read_plan_text(state: &RunProjection) -> Option<String> {
let mut plan_nodes = state
.nodes
.iter()
@ -907,7 +907,7 @@ mod tests {
#[test]
fn read_plan_text_found() {
let mut state = RunState::default();
let mut state = RunProjection::default();
state.nodes.insert(
("plan".to_string(), 1),
fabro_store::NodeState {
@ -922,7 +922,7 @@ mod tests {
#[test]
fn read_plan_text_prefix_match() {
let mut state = RunState::default();
let mut state = RunProjection::default();
state.nodes.insert(
("planning".to_string(), 1),
fabro_store::NodeState {
@ -937,7 +937,7 @@ mod tests {
#[test]
fn read_plan_text_prefers_alphabetically_first_plan_node() {
let mut state = RunState::default();
let mut state = RunProjection::default();
state.nodes.insert(
("planning".to_string(), 1),
fabro_store::NodeState {
@ -959,7 +959,7 @@ mod tests {
#[test]
fn read_plan_text_not_found() {
let mut state = RunState::default();
let mut state = RunProjection::default();
state.nodes.insert(
("implement".to_string(), 1),
fabro_store::NodeState::default(),
@ -971,7 +971,7 @@ mod tests {
#[test]
fn read_plan_text_empty_state() {
let state = RunState::default();
let state = RunProjection::default();
let result = read_plan_text(&state);
assert_eq!(result, None);
}

View file

@ -2,7 +2,7 @@ use std::io::Write;
use std::path::{Component, Path, PathBuf};
use anyhow::{Context, Result, bail};
use fabro_store::{NodeVisitRef, RunState, SlateRunStore};
use fabro_store::{NodeVisitRef, RunProjection, SlateRunStore};
use crate::git::MetadataStore;
@ -26,7 +26,7 @@ pub enum RunDumpContents {
impl RunDump {
#[must_use]
pub fn metadata_init(state: &RunState) -> Self {
pub fn metadata_init(state: &RunProjection) -> Self {
let mut entries = Vec::new();
if let Some(record) = state.run.as_ref() {
push_json_entry(&mut entries, "run.json", record);
@ -41,7 +41,7 @@ impl RunDump {
}
#[must_use]
pub fn metadata_checkpoint(state: &RunState) -> Self {
pub fn metadata_checkpoint(state: &RunProjection) -> Self {
let mut entries = Vec::new();
let mut keys: Vec<_> = state.nodes.keys().collect();
keys.sort();
@ -106,7 +106,7 @@ impl RunDump {
}
#[must_use]
pub fn metadata_finalize(state: &RunState) -> Self {
pub fn metadata_finalize(state: &RunProjection) -> Self {
let mut dump = Self::metadata_checkpoint(state);
if let Some(retro) = state.retro.as_ref() {
push_json_entry(&mut dump.entries, "retro.json", retro);
@ -114,7 +114,7 @@ impl RunDump {
dump
}
pub async fn store_export(run_store: &SlateRunStore, state: &RunState) -> Result<Self> {
pub async fn store_export(run_store: &SlateRunStore, state: &RunProjection) -> Result<Self> {
let mut entries = Vec::new();
if let Some(record) = state.run.as_ref() {