workdir: centralize workspace inventory contract

This commit is contained in:
2026-08-15 03:29:53 +09:00
parent 4cf34375a8
commit b910efd945
11 changed files with 449 additions and 218 deletions
+5 -59
View File
@@ -92,12 +92,11 @@ pub struct WorkingDirectoryRepository {
pub selector: Option<RepositorySelector>,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum MaterializerKind {
#[default]
LocalGitWorktree,
}
pub use workdir::workspace::{
MaterializerKind, WorkingDirectoryCleanupTarget, WorkingDirectoryCurrentObservation,
WorkingDirectoryOccupancy, WorkingDirectoryProvenance, WorkingDirectoryStatusKind,
WorkingDirectorySummary,
};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct WorkingDirectoryRequest {
@@ -117,59 +116,6 @@ pub struct WorkingDirectoryClaim {
pub relative_cwd: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum WorkingDirectoryStatusKind {
Active,
CleanupPending,
Corrupted,
NotFound,
Unknown,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct WorkingDirectoryCleanupTarget {
pub kind: String,
pub working_directory_id: String,
pub repository_id: String,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct WorkingDirectoryOccupancy {
#[serde(flatten)]
pub worker: RuntimeWorkerRef,
pub display_name: String,
pub linked_at: String,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct WorkingDirectorySummary {
pub working_directory_id: String,
pub repository_id: String,
/// Selector used to create this Workdir, retained as immutable materialization evidence.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub creation_selector: Option<String>,
/// Provider-specific immutable ref resolved when this Workdir was created.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub creation_ref: Option<String>,
/// Selector currently observed from the materialized Workdir, when one exists.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub current_selector: Option<String>,
/// Provider-specific immutable ref currently observed from the materialized Workdir.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub current_ref: Option<String>,
pub materializer_kind: MaterializerKind,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cleanup_target: Option<WorkingDirectoryCleanupTarget>,
pub status: WorkingDirectoryStatusKind,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cleanliness: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub primary_worker_id: Option<WorkerId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub occupied_by: Option<WorkingDirectoryOccupancy>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct WorkingDirectoryStatus {
pub summary: WorkingDirectorySummary,
+10 -22
View File
@@ -1,5 +1,6 @@
use serde::{Deserialize, Serialize};
use std::fmt;
pub use workdir::workspace::RuntimeWorkerRef;
/// Runtime-local Worker identity.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
@@ -30,29 +31,16 @@ impl fmt::Display for WorkerId {
}
}
/// Backend-visible Worker identity, namespaced by the Runtime that owns the Worker record.
///
/// This is intentionally distinct from [`WorkerRef`], which is meaningful only inside one
/// Runtime. Do not flatten this reference into a concatenated string for authority decisions.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct RuntimeWorkerRef {
pub runtime_id: String,
pub worker_id: String,
}
/// Convert an opaque Workspace Worker reference only at the Runtime-local boundary.
impl TryFrom<&RuntimeWorkerRef> for WorkerRef {
type Error = std::num::ParseIntError;
impl RuntimeWorkerRef {
pub fn new(runtime_id: impl Into<String>, worker_id: impl Into<String>) -> Self {
Self {
runtime_id: runtime_id.into(),
worker_id: worker_id.into(),
}
}
pub fn local_worker_ref(&self) -> Result<WorkerRef, std::num::ParseIntError> {
self.worker_id
fn try_from(value: &RuntimeWorkerRef) -> Result<Self, Self::Error> {
value
.worker_id
.parse::<u64>()
.map(WorkerId::new)
.map(WorkerRef::new)
.map(Self::new)
}
}
@@ -78,7 +66,7 @@ mod tests {
assert_eq!(worker.runtime_id, "arcadia");
assert_eq!(worker.worker_id, "30");
assert_eq!(
worker.local_worker_ref().unwrap(),
WorkerRef::try_from(&worker).unwrap(),
WorkerRef::new(WorkerId::new(30))
);
assert_eq!(
@@ -90,6 +78,6 @@ mod tests {
#[test]
fn runtime_worker_ref_does_not_treat_composite_text_as_local_worker_id() {
let worker = RuntimeWorkerRef::new("arcadia", "embedded-worker-runtime-5");
assert!(worker.local_worker_ref().is_err());
assert!(WorkerRef::try_from(&worker).is_err());
}
}
+3 -2
View File
@@ -467,8 +467,9 @@ impl Runtime {
mut status: CatalogWorkingDirectoryStatus,
) -> Result<CatalogWorkingDirectoryStatus, RuntimeError> {
let state = self.lock()?;
status.summary.primary_worker_id =
state.primary_worker_id_for_workdir(status.summary.working_directory_id.as_str());
status.summary.primary_worker_id = state
.primary_worker_id_for_workdir(status.summary.working_directory_id.as_str())
.map(|worker_id| worker_id.as_u64());
Ok(status)
}
+3 -4
View File
@@ -154,7 +154,7 @@ impl WorkerObservationProvider for RuntimeGrantedWorkerObservationProvider {
if grant.runtime_id != self.runtime_id {
continue;
}
let Ok(worker_ref) = grant.local_worker_ref() else {
let Ok(worker_ref) = WorkerRef::try_from(grant) else {
continue;
};
let Some((workspace_id, state, _)) = self.hub.get(&worker_ref) else {
@@ -192,9 +192,8 @@ impl WorkerObservationProvider for RuntimeGrantedWorkerObservationProvider {
if !self.grants.contains(&grant) || runtime_id != &self.runtime_id {
return Err(WorkerObservationError::NotFound);
}
let worker_ref = grant
.local_worker_ref()
.map_err(|_| WorkerObservationError::NotFound)?;
let worker_ref =
WorkerRef::try_from(&grant).map_err(|_| WorkerObservationError::NotFound)?;
let (workspace_id, _, sink) = self
.hub
.get(&worker_ref)