pub struct LoadedWorkspace {Show 15 fields
pub key: WorkspaceKey,
pub graph: ArcSwap<CodeGraph>,
pub state: AtomicU8,
pub last_accessed: RwLock<Instant>,
pub memory_bytes: AtomicUsize,
pub memory_high_water_bytes: AtomicUsize,
pub pinned: bool,
pub last_error: RwLock<Option<DaemonError>>,
pub last_good_at: RwLock<Option<SystemTime>>,
pub retry_count: AtomicU32,
pub rebuild_lane: Mutex<Option<PendingRebuild>>,
pub rebuild_cancelled: AtomicBool,
pub rebuild_in_flight: AtomicBool,
pub last_indexed_git_state: RwLock<Option<LastIndexedGitState>>,
pub nl_translator: OnceCell<Arc<Translator>>,
}Expand description
Per-workspace runtime state owned by the
super::WorkspaceManager::workspaces map.
Mutating state:
graph,state,memory_bytes,memory_high_water_bytes,retry_count,rebuild_cancelledare all atomic — queries and status readers can observe them without taking a mutex.last_accessed,last_error,last_good_atare short-critical- sectionRwLocks — writers are the dispatcher / router at publish/fail time.rebuild_laneis atokio::sync::Mutexper A2 §J.4; the dispatcher holds it briefly to coalesce pending work.
Construction is expensive only in that ArcSwap::new allocates
one Arc<CodeGraph> up front. A fresh workspace is initialised with
an empty-but-live CodeGraph; the real graph is installed by the
first publish_and_retain.
Fields§
§key: WorkspaceKeyIdentity key under which the manager stores this workspace.
Immutable for the lifetime of the workspace; if the config fingerprint or root mode change, the workspace is unloaded under the old key and freshly loaded under a new key.
graph: ArcSwap<CodeGraph>Published graph. Readers call graph.load_full().
Only [crate::workspace::publish::publish_and_retain] swaps a
new graph in; eviction stores a fresh empty graph so the
ArcSwap remains non-null (simpler than Option-wrapping).
state: AtomicU8Current lifecycle state. Stored as AtomicU8 to keep the
status read path lock-free; round-trip via
WorkspaceState::as_u8 / WorkspaceState::from_u8.
last_accessed: RwLock<Instant>Last wall-clock time a query observed this workspace, used by
LRU eviction (§G.7). Short critical section; RwLock keeps
contention negligible.
memory_bytes: AtomicUsizeCurrent heap_bytes of the published graph. Updated on every
successful publish_and_retain. Reads use Relaxed ordering —
the authoritative aggregate lives on
super::admission::AdmissionState.
memory_high_water_bytes: AtomicUsizePeak memory_bytes observed over this workspace’s loaded
lifetime. Per Amendment 2 §D:
High-water marks are monotonic over the workspace’s loaded lifetime — they reset only on unload/eviction (fresh LoadedWorkspace), not on rebuilds or backoff.
Updated via fetch_max alongside every memory_bytes store.
pinned: boolWhether LRU eviction must skip this workspace.
last_error: RwLock<Option<DaemonError>>Most recent build/load error, if any. None in the
WorkspaceState::Loaded steady state. Populated on transition
into WorkspaceState::Failed and read back by the router
when surfacing meta.last_error on stale responses.
last_good_at: RwLock<Option<SystemTime>>Wall-clock of the most recent successful rebuild. Used by the
router to compute age_hours for the
stale_serve_max_age_hours cap and the JSON-RPC -32002
error error.data.age_hours payload.
retry_count: AtomicU32Count of consecutive failed rebuilds. Drives the exponential backoff schedule (§G.7 / plan Step 6: 30s → 60s → 120s → 300s → 600s). Reset to 0 on every successful publish.
rebuild_lane: Mutex<Option<PendingRebuild>>At most one queued rebuild per workspace. None when the
dispatcher’s lane is idle. Filled / coalesced by the
dispatcher (Task 7).
rebuild_cancelled: AtomicBoolLock-free cancellation signal for in-flight rebuilds. Set by
evict_lru / explicit unload and polled by the rebuild
pipeline at each pass boundary. Once set, the running rebuild
aborts, drops its RebuildReservation, and never publishes.
rebuild_in_flight: AtomicBoolRunner-role gate for the per-workspace rebuild serial consumer
(A2 §J.2, Task 7 Phase 7b1). When true, exactly one
crate::RebuildDispatcher::handle_changes call is actively
running the full rebuild pipeline (the Phase B drain loop in
rebuild.rs). A concurrent caller observing true under the
Self::rebuild_lane lock MUST park its coalesced
PendingRebuild in the lane and return Ok(()) without
executing — the active runner will drain the lane at its next
drain-loop iteration.
§Invariant
All normal-path transitions of this flag happen while
Self::rebuild_lane is held. DrainLoopSentinel::drop in
rebuild.rs is the sole recovery exception — it stores false
without the lane on the unwind path, with the narrow-race
semantics documented on that type.
§Authorised modifiers
RebuildDispatcher::handle_changesPhase A (false → trueunder lane).RebuildDispatcher::handle_changesPhase B drain-loop exit (true → falseunder lane, when the lane is empty or the top-of-loop eviction gate fires).DrainLoopSentinel::droppanic-safety path (true → false, bare atomic store, narrow race).
Nothing in WorkspaceManager (execute_eviction,
publish_and_retain, the retention reaper) touches this flag.
It is dispatcher-local coordination, independent of the
rebuild_cancelled eviction signal.
last_indexed_git_state: RwLock<Option<LastIndexedGitState>>Git state that the currently-published graph was indexed against (Task 7 Phase 7b2, A2 §I / §J.2).
Read by the per-workspace watcher bridge as the last_git_state
argument to
sqry_core::watch::SourceTreeWatcher::wait_for_changes_cancellable
so the classifier has a valid baseline on every debounce window.
Advanced ONLY by crate::RebuildDispatcher::execute_one_rebuild
after crate::WorkspaceManager::publish_and_retain succeeds,
using the git_state_at_enqueue snapshot attached to the
PendingRebuild that produced the publish. A failed rebuild
MUST leave this field unchanged so the next
wait_for_changes_cancellable call still sees the divergent
state and retries.
§Invariant
- Only
execute_one_rebuild’s successful-publish arm writes this field. - Watcher-side event receipt, cancellation, or rebuild failure never write this field.
- The write happens under
parking_lot::RwLock— short critical section, no cross-lock ordering concerns.
None on workspace construction (no rebuild has published
yet). The first successful execute_one_rebuild driven by the
watcher bridge (which attaches git_state_at_enqueue = Some(...))
populates this field.
nl_translator: OnceCell<Arc<Translator>>NL07 — lazily-initialised, per-workspace
sqry_nl::Translator backing the daemon-hosted sqry_ask
MCP tool.
Init cost is heavy (O(seconds) — N parallel ONNX session
loads from the sqry_nl::classifier::ClassifierPool) so the
daemon defers it to the first sqry_ask call against the
workspace via OnceCell::get_or_try_init. Subsequent calls
receive a cheap Arc<Translator> clone.
Lifetime: tied to LoadedWorkspace itself. Workspace
eviction (LRU, explicit unload, daemon shutdown) drops the
OnceCell, which drops the Arc<Translator>, which drops
the pool’s N classifier sessions and frees their model
weights. No explicit cleanup required.
Concurrency: the cell itself is Send + Sync. The
Translator inside uses an internal sync pool that the
daemon’s MCP host calls under tokio::task::spawn_blocking
so the daemon’s tokio runtime never blocks on recv().
Implementations§
Source§impl LoadedWorkspace
impl LoadedWorkspace
Sourcepub fn new(key: WorkspaceKey, pinned: bool) -> Self
pub fn new(key: WorkspaceKey, pinned: bool) -> Self
Construct a fresh workspace entry with an empty initial graph.
The empty graph is Arc-cheap (sub-kilobyte) so keeping the
ArcSwap non-null for the entire workspace lifetime avoids an
Option layer on the query path. Eviction stores another
empty graph through the same ArcSwap; re-load overwrites it.
Sourcepub fn load_state(&self) -> WorkspaceState
pub fn load_state(&self) -> WorkspaceState
Atomic state read. Round-trips through WorkspaceState::from_u8;
a discriminant outside the current range panics (it is a
telemetry-corruption bug, not a recoverable condition).
Sourcepub fn store_state(&self, new_state: WorkspaceState)
pub fn store_state(&self, new_state: WorkspaceState)
Atomic state write.
Sourcepub fn update_memory(&self, new_bytes: usize) -> usize
pub fn update_memory(&self, new_bytes: usize) -> usize
Update memory_bytes and keep memory_high_water_bytes
monotonic. Matches Amendment 2 §D:
Every time
memory_bytesis assigned (initial load, full rebuild completion, incremental rebuild’sArcSwap::store), immediately callmemory_high_water_bytes.fetch_max(new, Relaxed).
Returns the previous memory_bytes value so the caller can
compute the delta the admission accounting needs.
Sourcepub fn touch(&self)
pub fn touch(&self)
Stamp last_accessed = now on a query. Held under an RwLock
so the query hot path never blocks — writers contend only with
other writers.
Sourcepub fn record_success(&self, at: SystemTime)
pub fn record_success(&self, at: SystemTime)
Record a successful build’s wall-clock + reset retry counter.
Sourcepub fn record_failure(&self, err: DaemonError) -> u32
pub fn record_failure(&self, err: DaemonError) -> u32
Record a failed build and return the new retry count. The dispatcher uses this to pick the exponential-backoff schedule.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for LoadedWorkspace
impl !RefUnwindSafe for LoadedWorkspace
impl Send for LoadedWorkspace
impl Sync for LoadedWorkspace
impl Unpin for LoadedWorkspace
impl UnsafeUnpin for LoadedWorkspace
impl !UnwindSafe for LoadedWorkspace
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<D> OwoColorize for D
impl<D> OwoColorize for D
Source§fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
Source§fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
Source§fn black(&self) -> FgColorDisplay<'_, Black, Self>
fn black(&self) -> FgColorDisplay<'_, Black, Self>
Source§fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
Source§fn red(&self) -> FgColorDisplay<'_, Red, Self>
fn red(&self) -> FgColorDisplay<'_, Red, Self>
Source§fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
Source§fn green(&self) -> FgColorDisplay<'_, Green, Self>
fn green(&self) -> FgColorDisplay<'_, Green, Self>
Source§fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
Source§fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
Source§fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
Source§fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
Source§fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
Source§fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
Source§fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
Source§fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
Source§fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
Source§fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
Source§fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
Source§fn white(&self) -> FgColorDisplay<'_, White, Self>
fn white(&self) -> FgColorDisplay<'_, White, Self>
Source§fn on_white(&self) -> BgColorDisplay<'_, White, Self>
fn on_white(&self) -> BgColorDisplay<'_, White, Self>
Source§fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
Source§fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
Source§fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
Source§fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
Source§fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
Source§fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
Source§fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
Source§fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
Source§fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
Source§fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
Source§fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
Source§fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
Source§fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
Source§fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
Source§fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
Source§fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
Source§fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
Source§fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
Source§fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
Source§fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
Source§fn bold(&self) -> BoldDisplay<'_, Self>
fn bold(&self) -> BoldDisplay<'_, Self>
Source§fn dimmed(&self) -> DimDisplay<'_, Self>
fn dimmed(&self) -> DimDisplay<'_, Self>
Source§fn italic(&self) -> ItalicDisplay<'_, Self>
fn italic(&self) -> ItalicDisplay<'_, Self>
Source§fn underline(&self) -> UnderlineDisplay<'_, Self>
fn underline(&self) -> UnderlineDisplay<'_, Self>
Source§fn blink(&self) -> BlinkDisplay<'_, Self>
fn blink(&self) -> BlinkDisplay<'_, Self>
Source§fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
Source§fn reversed(&self) -> ReversedDisplay<'_, Self>
fn reversed(&self) -> ReversedDisplay<'_, Self>
Source§fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
Source§fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::fg or
a color-specific method, such as OwoColorize::green, Read moreSource§fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::bg or
a color-specific method, such as OwoColorize::on_yellow, Read more