fix: make WorkerId the standalone primary identity

This commit is contained in:
2026-08-31 14:37:46 +09:00
parent bde1dea2a5
commit e7f4c6864f
16 changed files with 444 additions and 437 deletions
+51 -43
View File
@@ -14,7 +14,7 @@ use futures::{Stream, stream};
use protocol::{Event, Method};
use standalone::{
StaleLeasePolicy, StandaloneHost, StandaloneLaunchConfig, StandaloneListScope,
StandaloneSessionStatus, StandaloneSessionStore, StandaloneStartupError, StandaloneStoreError,
StandaloneStartupError, StandaloneStoreError, StandaloneWorkerStatus, StandaloneWorkerStore,
};
use uuid::Uuid;
@@ -90,6 +90,12 @@ async fn in_process_host_runs_text_and_read_tool_then_shuts_down() {
let host = StandaloneHost::start_with_model_client(launch, client)
.await
.expect("start in-process host");
assert_eq!(host.record().worker_name, worker_name);
assert_eq!(host.record().manifest.worker.name, worker_name);
assert_eq!(
host.record().storage_key,
format!("standalone-{}", host.worker_id())
);
let mut protocol_client = host.connect();
protocol_client
@@ -238,7 +244,7 @@ type TestResult = Result<(), Box<dyn std::error::Error>>;
async fn standalone_restore_preserves_history_tasks_notifications_and_cwd_scope() -> TestResult {
let temp = tempfile::tempdir()?;
let cwd = temp.path().join("project");
let state_dir = temp.path().join("client").join("standalone-sessions");
let state_dir = temp.path().join("client").join("standalone-workers");
std::fs::create_dir_all(&cwd)?;
let launch = StandaloneLaunchConfig::new(
&cwd,
@@ -268,7 +274,7 @@ async fn standalone_restore_preserves_history_tasks_notifications_and_cwd_scope(
],
]);
let host = StandaloneHost::start_with_model_client(launch, first_client).await?;
let session_id = host.session_id();
let worker_id = host.worker_id();
let mut protocol_client = host.connect();
protocol_client
.send(&Method::run_text("first request"))
@@ -283,11 +289,11 @@ async fn standalone_restore_preserves_history_tasks_notifications_and_cwd_scope(
wait_for_run_end(&mut protocol_client).await?;
host.shutdown().await?;
let store = StandaloneSessionStore::open(&state_dir)?;
let store = StandaloneWorkerStore::open(&state_dir)?;
let current = store.list(&cwd, StandaloneListScope::CurrentCwd, 100)?;
assert_eq!(current.len(), 1);
assert_eq!(current[0].session_id, session_id);
assert_eq!(current[0].status, StandaloneSessionStatus::Stopped);
assert_eq!(current[0].worker_id, worker_id);
assert_eq!(current[0].status, StandaloneWorkerStatus::Stopped);
let other_cwd = temp.path().join("other");
std::fs::create_dir(&other_cwd)?;
assert!(
@@ -307,8 +313,13 @@ async fn standalone_restore_preserves_history_tasks_notifications_and_cwd_scope(
]]);
let second_inspection = second_client.clone();
let host =
StandaloneHost::restore_with_model_client(state_dir.clone(), session_id, second_client)
StandaloneHost::restore_with_model_client(state_dir.clone(), worker_id, second_client)
.await?;
assert_eq!(
host.record().worker_name,
"display-name-is-not-session-identity"
);
assert_eq!(host.record().storage_key, format!("standalone-{worker_id}"));
let mut protocol_client = host.connect();
let snapshot = format!(
"{:?}",
@@ -338,11 +349,11 @@ async fn standalone_restore_preserves_history_tasks_notifications_and_cwd_scope(
assert!(projected.contains("persisted task"), "{projected}");
host.shutdown().await?;
store.delete(session_id)?;
store.delete(worker_id)?;
assert!(cwd.exists(), "deleting session state must not mutate cwd");
assert!(matches!(
store.load(session_id),
Err(StandaloneStoreError::SessionNotFound(_))
store.load(worker_id),
Err(StandaloneStoreError::WorkerNotFound(_))
));
Ok(())
}
@@ -363,28 +374,25 @@ async fn standalone_restore_rejects_concurrent_lease_and_missing_cwd() -> TestRe
.resolve()?;
let host =
StandaloneHost::start_with_model_client(launch, ScriptedClient::new(Vec::new())).await?;
let session_id = host.session_id();
let store = StandaloneSessionStore::open(&state_dir)?;
let worker_id = host.worker_id();
let store = StandaloneWorkerStore::open(&state_dir)?;
assert!(matches!(
store.acquire_lease(session_id, StaleLeasePolicy::Recover),
Err(StandaloneStoreError::SessionLeased(id)) if id == session_id
store.acquire_lease(worker_id, StaleLeasePolicy::Recover),
Err(StandaloneStoreError::WorkerLeased(id)) if id == worker_id
));
let restore = StandaloneHost::restore_with_model_client(
state_dir.clone(),
session_id,
worker_id,
ScriptedClient::new(Vec::new()),
)
.await;
assert!(matches!(
restore,
Err(StandaloneStartupError::SessionActive)
));
assert!(matches!(restore, Err(StandaloneStartupError::WorkerActive)));
host.shutdown().await?;
std::fs::rename(&cwd, &moved)?;
let restore = StandaloneHost::restore_with_model_client(
state_dir,
session_id,
worker_id,
ScriptedClient::new(Vec::new()),
)
.await;
@@ -421,11 +429,11 @@ async fn standalone_restore_recovers_only_a_proven_stale_lease() -> TestResult {
});
let host =
StandaloneHost::start_with_model_client(launch, ScriptedClient::new(Vec::new())).await?;
let session_id = host.session_id();
let worker_id = host.worker_id();
host.shutdown().await?;
let store = StandaloneSessionStore::open(&state_dir)?;
let store = StandaloneWorkerStore::open(&state_dir)?;
assert!(matches!(
store.load(session_id)?.manifest.profile,
store.load(worker_id)?.manifest.profile,
Some(manifest::ProfileManifestSnapshot {
source: manifest::ProfileSource::Registry {
source: manifest::ProfileRegistrySource::User,
@@ -434,9 +442,9 @@ async fn standalone_restore_recovers_only_a_proven_stale_lease() -> TestResult {
..
})
));
let session_dir = state_dir.join(session_id.to_string());
let worker_dir = state_dir.join(worker_id.to_string());
std::fs::write(
session_dir.join("lease.json"),
worker_dir.join("lease.json"),
serde_json::to_vec(&serde_json::json!({
"lease_id": uuid::Uuid::now_v7(),
"pid": u32::MAX,
@@ -447,7 +455,7 @@ async fn standalone_restore_recovers_only_a_proven_stale_lease() -> TestResult {
let host = StandaloneHost::restore_with_model_client(
state_dir,
session_id,
worker_id,
ScriptedClient::new(Vec::new()),
)
.await?;
@@ -468,11 +476,11 @@ async fn standalone_restore_rejects_lease_with_missing_start_marker() -> TestRes
.resolve()?;
let host =
StandaloneHost::start_with_model_client(launch, ScriptedClient::new(Vec::new())).await?;
let session_id = host.session_id();
let worker_id = host.worker_id();
host.shutdown().await?;
let session_dir = state_dir.join(session_id.to_string());
let worker_dir = state_dir.join(worker_id.to_string());
std::fs::write(
session_dir.join("lease.json"),
worker_dir.join("lease.json"),
serde_json::to_vec(&serde_json::json!({
"lease_id": uuid::Uuid::now_v7(),
"pid": std::process::id(),
@@ -480,14 +488,14 @@ async fn standalone_restore_rejects_lease_with_missing_start_marker() -> TestRes
}))?,
)?;
let store = StandaloneSessionStore::open(&state_dir)?;
let store = StandaloneWorkerStore::open(&state_dir)?;
assert!(matches!(
store.acquire_lease(session_id, StaleLeasePolicy::Recover),
Err(StandaloneStoreError::LeaseLivenessUnknown(id)) if id == session_id
store.acquire_lease(worker_id, StaleLeasePolicy::Recover),
Err(StandaloneStoreError::LeaseLivenessUnknown(id)) if id == worker_id
));
let restore = StandaloneHost::restore_with_model_client(
state_dir,
session_id,
worker_id,
ScriptedClient::new(Vec::new()),
)
.await;
@@ -511,23 +519,23 @@ async fn standalone_metadata_fails_closed_on_incomplete_or_newer_records() -> Te
.resolve()?;
let host =
StandaloneHost::start_with_model_client(launch, ScriptedClient::new(Vec::new())).await?;
let session_id = host.session_id();
let worker_id = host.worker_id();
host.shutdown().await?;
let store = StandaloneSessionStore::open(&state_dir)?;
let session_dir = state_dir.join(session_id.to_string());
std::fs::write(session_dir.join("commit.pending"), b"interrupted\n")?;
let store = StandaloneWorkerStore::open(&state_dir)?;
let worker_dir = state_dir.join(worker_id.to_string());
std::fs::write(worker_dir.join("commit.pending"), b"interrupted\n")?;
assert!(matches!(
store.load(session_id),
Err(StandaloneStoreError::IncompleteCommit(id)) if id == session_id
store.load(worker_id),
Err(StandaloneStoreError::IncompleteCommit(id)) if id == worker_id
));
std::fs::remove_file(session_dir.join("commit.pending"))?;
let record_path = session_dir.join("record.json");
std::fs::remove_file(worker_dir.join("commit.pending"))?;
let record_path = worker_dir.join("record.json");
let mut record: serde_json::Value = serde_json::from_slice(&std::fs::read(&record_path)?)?;
record["schema_version"] = serde_json::json!(u32::MAX);
std::fs::write(&record_path, serde_json::to_vec_pretty(&record)?)?;
assert!(matches!(
store.load(session_id),
Err(StandaloneStoreError::NewerSchema { id, .. }) if id == session_id
store.load(worker_id),
Err(StandaloneStoreError::NewerSchema { id, .. }) if id == worker_id
));
Ok(())
}