fix: remove workdir management kind
This commit is contained in:
parent
fe2a39c12d
commit
44deacb3f4
|
|
@ -123,8 +123,6 @@ pub struct BackendWorkingDirectorySummary {
|
||||||
pub cleanliness: Option<String>,
|
pub cleanliness: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub primary_worker_id: Option<String>,
|
pub primary_worker_id: Option<String>,
|
||||||
#[serde(default)]
|
|
||||||
pub management_kind: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
|
||||||
|
|
|
||||||
|
|
@ -156,10 +156,6 @@ pub struct WorkingDirectorySummary {
|
||||||
pub cleanliness: Option<String>,
|
pub cleanliness: Option<String>,
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub primary_worker_id: Option<WorkerId>,
|
pub primary_worker_id: Option<WorkerId>,
|
||||||
/// Backend projection metadata. Runtimes leave this absent; Workspace Browser
|
|
||||||
/// APIs fill it with `backend_managed` or `runtime_unmanaged`.
|
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
||||||
pub management_kind: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,6 @@ impl WorkingDirectory {
|
||||||
status: self.status.clone(),
|
status: self.status.clone(),
|
||||||
cleanliness: None,
|
cleanliness: None,
|
||||||
primary_worker_id: None,
|
primary_worker_id: None,
|
||||||
management_kind: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +221,6 @@ impl LocalGitWorktreeMaterializer {
|
||||||
status: WorkingDirectoryStatusKind::Corrupted,
|
status: WorkingDirectoryStatusKind::Corrupted,
|
||||||
cleanliness: Some("unknown".to_string()),
|
cleanliness: Some("unknown".to_string()),
|
||||||
primary_worker_id: None,
|
primary_worker_id: None,
|
||||||
management_kind: None,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1587,7 +1587,6 @@ fn create_working_directory_for_runtime(
|
||||||
resolved_commit: None,
|
resolved_commit: None,
|
||||||
materialization_status: "pending".to_string(),
|
materialization_status: "pending".to_string(),
|
||||||
cleanliness: "unknown".to_string(),
|
cleanliness: "unknown".to_string(),
|
||||||
management_kind: "backend_managed".to_string(),
|
|
||||||
created_at: now_registry_timestamp(),
|
created_at: now_registry_timestamp(),
|
||||||
updated_at: now_registry_timestamp(),
|
updated_at: now_registry_timestamp(),
|
||||||
};
|
};
|
||||||
|
|
@ -1610,12 +1609,7 @@ fn create_working_directory_for_runtime(
|
||||||
result.diagnostics,
|
result.diagnostics,
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
let record = workdir_record_from_summary(
|
let record = workdir_record_from_summary(&api, &runtime_id, &working_directory.summary);
|
||||||
&api,
|
|
||||||
&runtime_id,
|
|
||||||
&working_directory.summary,
|
|
||||||
"backend_managed",
|
|
||||||
);
|
|
||||||
api.store.upsert_workdir_registry(&record)?;
|
api.store.upsert_workdir_registry(&record)?;
|
||||||
Ok(Json(BrowserWorkingDirectoryDetailResponse {
|
Ok(Json(BrowserWorkingDirectoryDetailResponse {
|
||||||
workspace_id: api.config.workspace_id.clone(),
|
workspace_id: api.config.workspace_id.clone(),
|
||||||
|
|
@ -1634,17 +1628,7 @@ fn working_directory_detail_for_runtime(
|
||||||
.working_directory(runtime_id, working_directory_id)
|
.working_directory(runtime_id, working_directory_id)
|
||||||
.map_err(|err| err.into_error())?;
|
.map_err(|err| err.into_error())?;
|
||||||
if let Some(working_directory) = result.working_directory {
|
if let Some(working_directory) = result.working_directory {
|
||||||
let management_kind = api
|
let record = workdir_record_from_summary(&api, runtime_id, &working_directory.summary);
|
||||||
.store
|
|
||||||
.get_workdir_registry(&api.config.workspace_id, working_directory_id)?
|
|
||||||
.map(|record| record.management_kind)
|
|
||||||
.unwrap_or_else(|| "runtime_unmanaged".to_string());
|
|
||||||
let record = workdir_record_from_summary(
|
|
||||||
&api,
|
|
||||||
runtime_id,
|
|
||||||
&working_directory.summary,
|
|
||||||
management_kind.as_str(),
|
|
||||||
);
|
|
||||||
api.store.upsert_workdir_registry(&record)?;
|
api.store.upsert_workdir_registry(&record)?;
|
||||||
return Ok(Json(BrowserWorkingDirectoryDetailResponse {
|
return Ok(Json(BrowserWorkingDirectoryDetailResponse {
|
||||||
workspace_id: api.config.workspace_id.clone(),
|
workspace_id: api.config.workspace_id.clone(),
|
||||||
|
|
@ -1711,17 +1695,7 @@ fn cleanup_working_directory_for_runtime(
|
||||||
result.diagnostics,
|
result.diagnostics,
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
let management_kind = api
|
let record = workdir_record_from_summary(&api, runtime_id, &working_directory.summary);
|
||||||
.store
|
|
||||||
.get_workdir_registry(&api.config.workspace_id, working_directory_id)?
|
|
||||||
.map(|record| record.management_kind)
|
|
||||||
.unwrap_or_else(|| "runtime_unmanaged".to_string());
|
|
||||||
let record = workdir_record_from_summary(
|
|
||||||
&api,
|
|
||||||
runtime_id,
|
|
||||||
&working_directory.summary,
|
|
||||||
management_kind.as_str(),
|
|
||||||
);
|
|
||||||
api.store.upsert_workdir_registry(&record)?;
|
api.store.upsert_workdir_registry(&record)?;
|
||||||
Ok(Json(BrowserWorkingDirectoryDetailResponse {
|
Ok(Json(BrowserWorkingDirectoryDetailResponse {
|
||||||
workspace_id: api.config.workspace_id.clone(),
|
workspace_id: api.config.workspace_id.clone(),
|
||||||
|
|
@ -3010,20 +2984,8 @@ async fn create_workspace_worker(
|
||||||
WorkerRegistryDisplayNamePolicy::UseProvided,
|
WorkerRegistryDisplayNamePolicy::UseProvided,
|
||||||
)?;
|
)?;
|
||||||
if let Some(working_directory) = worker.working_directory.as_ref() {
|
if let Some(working_directory) = worker.working_directory.as_ref() {
|
||||||
let management_kind = api
|
let workdir_record =
|
||||||
.store
|
workdir_record_from_summary(&api, worker.runtime_id.as_str(), working_directory);
|
||||||
.get_workdir_registry(
|
|
||||||
&api.config.workspace_id,
|
|
||||||
&working_directory.working_directory_id,
|
|
||||||
)?
|
|
||||||
.map(|existing| existing.management_kind)
|
|
||||||
.unwrap_or_else(|| "runtime_unmanaged".to_string());
|
|
||||||
let workdir_record = workdir_record_from_summary(
|
|
||||||
&api,
|
|
||||||
worker.runtime_id.as_str(),
|
|
||||||
working_directory,
|
|
||||||
management_kind.as_str(),
|
|
||||||
);
|
|
||||||
api.store.upsert_workdir_registry(&workdir_record)?;
|
api.store.upsert_workdir_registry(&workdir_record)?;
|
||||||
link_worker_to_workdir(
|
link_worker_to_workdir(
|
||||||
&api,
|
&api,
|
||||||
|
|
@ -3047,7 +3009,6 @@ async fn create_workspace_worker(
|
||||||
&api,
|
&api,
|
||||||
worker.runtime_id.as_str(),
|
worker.runtime_id.as_str(),
|
||||||
&status.summary,
|
&status.summary,
|
||||||
"runtime_unmanaged",
|
|
||||||
);
|
);
|
||||||
api.store.upsert_workdir_registry(&record)?;
|
api.store.upsert_workdir_registry(&record)?;
|
||||||
}
|
}
|
||||||
|
|
@ -4425,7 +4386,7 @@ fn working_directory_summaries(api: &WorkspaceApi) -> ApiResult<Vec<WorkingDirec
|
||||||
let _ = sync_all_runtime_workdir_observations(api);
|
let _ = sync_all_runtime_workdir_observations(api);
|
||||||
let records = api
|
let records = api
|
||||||
.store
|
.store
|
||||||
.list_managed_workdir_registry(&api.config.workspace_id, 200)?;
|
.list_workdir_registry(&api.config.workspace_id, 200)?;
|
||||||
Ok(records
|
Ok(records
|
||||||
.iter()
|
.iter()
|
||||||
.map(workdir_summary_from_record)
|
.map(workdir_summary_from_record)
|
||||||
|
|
@ -4619,20 +4580,8 @@ fn sync_worker_observation(
|
||||||
WorkerRegistryDisplayNamePolicy::PreserveExisting,
|
WorkerRegistryDisplayNamePolicy::PreserveExisting,
|
||||||
)?;
|
)?;
|
||||||
if let Some(working_directory) = worker.working_directory.as_ref() {
|
if let Some(working_directory) = worker.working_directory.as_ref() {
|
||||||
let management_kind = api
|
let workdir_record =
|
||||||
.store
|
workdir_record_from_summary(api, worker.runtime_id.as_str(), working_directory);
|
||||||
.get_workdir_registry(
|
|
||||||
&api.config.workspace_id,
|
|
||||||
&working_directory.working_directory_id,
|
|
||||||
)?
|
|
||||||
.map(|existing| existing.management_kind)
|
|
||||||
.unwrap_or_else(|| "runtime_unmanaged".to_string());
|
|
||||||
let workdir_record = workdir_record_from_summary(
|
|
||||||
api,
|
|
||||||
worker.runtime_id.as_str(),
|
|
||||||
working_directory,
|
|
||||||
management_kind.as_str(),
|
|
||||||
);
|
|
||||||
api.store.upsert_workdir_registry(&workdir_record)?;
|
api.store.upsert_workdir_registry(&workdir_record)?;
|
||||||
link_worker_to_workdir(api, &record, &working_directory.working_directory_id)?;
|
link_worker_to_workdir(api, &record, &working_directory.working_directory_id)?;
|
||||||
}
|
}
|
||||||
|
|
@ -4663,7 +4612,6 @@ fn upsert_pending_backend_workdir(
|
||||||
resolved_commit: None,
|
resolved_commit: None,
|
||||||
materialization_status: "pending".to_string(),
|
materialization_status: "pending".to_string(),
|
||||||
cleanliness: "unknown".to_string(),
|
cleanliness: "unknown".to_string(),
|
||||||
management_kind: "backend_managed".to_string(),
|
|
||||||
created_at: timestamp.clone(),
|
created_at: timestamp.clone(),
|
||||||
updated_at: timestamp,
|
updated_at: timestamp,
|
||||||
})?;
|
})?;
|
||||||
|
|
@ -4692,12 +4640,7 @@ fn sync_runtime_workdir_observations(
|
||||||
&api.config.workspace_id,
|
&api.config.workspace_id,
|
||||||
&status.summary.working_directory_id,
|
&status.summary.working_directory_id,
|
||||||
)?;
|
)?;
|
||||||
let management_kind = existing
|
let mut record = workdir_record_from_summary(api, runtime_id, &status.summary);
|
||||||
.as_ref()
|
|
||||||
.map(|existing| existing.management_kind.clone())
|
|
||||||
.unwrap_or_else(|| "runtime_unmanaged".to_string());
|
|
||||||
let mut record =
|
|
||||||
workdir_record_from_summary(api, runtime_id, &status.summary, management_kind.as_str());
|
|
||||||
preserve_workdir_identity_for_corrupted_summary(&mut record, existing.as_ref());
|
preserve_workdir_identity_for_corrupted_summary(&mut record, existing.as_ref());
|
||||||
api.store.upsert_workdir_registry(&record)?;
|
api.store.upsert_workdir_registry(&record)?;
|
||||||
}
|
}
|
||||||
|
|
@ -4719,13 +4662,8 @@ fn sync_runtime_workdir_observations(
|
||||||
record.workdir_id.as_str(),
|
record.workdir_id.as_str(),
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
let management_kind = record.management_kind.clone();
|
let mut updated =
|
||||||
let mut updated = workdir_record_from_summary(
|
workdir_record_from_summary(api, runtime_id, &status.summary);
|
||||||
api,
|
|
||||||
runtime_id,
|
|
||||||
&status.summary,
|
|
||||||
management_kind.as_str(),
|
|
||||||
);
|
|
||||||
preserve_workdir_identity_for_corrupted_summary(
|
preserve_workdir_identity_for_corrupted_summary(
|
||||||
&mut updated,
|
&mut updated,
|
||||||
Some(&record),
|
Some(&record),
|
||||||
|
|
@ -4792,17 +4730,7 @@ fn sync_linked_workdir_after_worker_stop(
|
||||||
.working_directory(runtime_id, link.workdir_id.as_str())
|
.working_directory(runtime_id, link.workdir_id.as_str())
|
||||||
.map_err(|err| err.into_error())?;
|
.map_err(|err| err.into_error())?;
|
||||||
if let Some(status) = result.working_directory {
|
if let Some(status) = result.working_directory {
|
||||||
let management_kind = api
|
let record = workdir_record_from_summary(api, runtime_id, &status.summary);
|
||||||
.store
|
|
||||||
.get_workdir_registry(&api.config.workspace_id, link.workdir_id.as_str())?
|
|
||||||
.map(|record| record.management_kind)
|
|
||||||
.unwrap_or_else(|| "runtime_unmanaged".to_string());
|
|
||||||
let record = workdir_record_from_summary(
|
|
||||||
api,
|
|
||||||
runtime_id,
|
|
||||||
&status.summary,
|
|
||||||
management_kind.as_str(),
|
|
||||||
);
|
|
||||||
api.store.upsert_workdir_registry(&record)?;
|
api.store.upsert_workdir_registry(&record)?;
|
||||||
} else if let Some(mut record) = api
|
} else if let Some(mut record) = api
|
||||||
.store
|
.store
|
||||||
|
|
@ -4822,7 +4750,6 @@ fn workdir_record_from_summary(
|
||||||
api: &WorkspaceApi,
|
api: &WorkspaceApi,
|
||||||
runtime_id: &str,
|
runtime_id: &str,
|
||||||
summary: &WorkingDirectorySummary,
|
summary: &WorkingDirectorySummary,
|
||||||
management_kind: &str,
|
|
||||||
) -> WorkdirRegistryRecord {
|
) -> WorkdirRegistryRecord {
|
||||||
let timestamp = now_registry_timestamp();
|
let timestamp = now_registry_timestamp();
|
||||||
WorkdirRegistryRecord {
|
WorkdirRegistryRecord {
|
||||||
|
|
@ -4844,7 +4771,6 @@ fn workdir_record_from_summary(
|
||||||
.cleanliness
|
.cleanliness
|
||||||
.clone()
|
.clone()
|
||||||
.unwrap_or_else(|| "unknown".to_string()),
|
.unwrap_or_else(|| "unknown".to_string()),
|
||||||
management_kind: management_kind.to_string(),
|
|
||||||
created_at: timestamp.clone(),
|
created_at: timestamp.clone(),
|
||||||
updated_at: timestamp,
|
updated_at: timestamp,
|
||||||
}
|
}
|
||||||
|
|
@ -4895,7 +4821,6 @@ fn workdir_summary_from_record(record: &WorkdirRegistryRecord) -> WorkingDirecto
|
||||||
status,
|
status,
|
||||||
cleanliness: Some(record.cleanliness.clone()),
|
cleanliness: Some(record.cleanliness.clone()),
|
||||||
primary_worker_id: None,
|
primary_worker_id: None,
|
||||||
management_kind: Some(record.management_kind.clone()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5517,7 +5442,6 @@ mod tests {
|
||||||
resolved_commit: Some("abcdef".to_string()),
|
resolved_commit: Some("abcdef".to_string()),
|
||||||
materialization_status: "missing".to_string(),
|
materialization_status: "missing".to_string(),
|
||||||
cleanliness: "clean".to_string(),
|
cleanliness: "clean".to_string(),
|
||||||
management_kind: "backend_managed".to_string(),
|
|
||||||
created_at: "1".to_string(),
|
created_at: "1".to_string(),
|
||||||
updated_at: "3".to_string(),
|
updated_at: "3".to_string(),
|
||||||
};
|
};
|
||||||
|
|
@ -5538,22 +5462,13 @@ mod tests {
|
||||||
projected.working_directory.as_ref().unwrap().status,
|
projected.working_directory.as_ref().unwrap().status,
|
||||||
WorkingDirectoryStatusKind::NotFound
|
WorkingDirectoryStatusKind::NotFound
|
||||||
);
|
);
|
||||||
assert_eq!(
|
|
||||||
projected
|
|
||||||
.working_directory
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.management_kind
|
|
||||||
.as_deref(),
|
|
||||||
Some("backend_managed")
|
|
||||||
);
|
|
||||||
let serialized = serde_json::to_string(&projected).unwrap();
|
let serialized = serde_json::to_string(&projected).unwrap();
|
||||||
assert!(!serialized.contains("/tmp/"));
|
assert!(!serialized.contains("/tmp/"));
|
||||||
assert!(!serialized.contains("materialized_path"));
|
assert!(!serialized.contains("materialized_path"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn workspace_managed_workdir_summaries_exclude_runtime_unmanaged_rows() {
|
async fn workspace_workdir_summaries_include_runtime_observed_rows() {
|
||||||
let dir = tempfile::tempdir().unwrap();
|
let dir = tempfile::tempdir().unwrap();
|
||||||
let api = test_api(dir.path()).await;
|
let api = test_api(dir.path()).await;
|
||||||
api.store
|
api.store
|
||||||
|
|
@ -5566,7 +5481,6 @@ mod tests {
|
||||||
resolved_commit: None,
|
resolved_commit: None,
|
||||||
materialization_status: "present".to_string(),
|
materialization_status: "present".to_string(),
|
||||||
cleanliness: "clean".to_string(),
|
cleanliness: "clean".to_string(),
|
||||||
management_kind: "backend_managed".to_string(),
|
|
||||||
created_at: "1".to_string(),
|
created_at: "1".to_string(),
|
||||||
updated_at: "1".to_string(),
|
updated_at: "1".to_string(),
|
||||||
})
|
})
|
||||||
|
|
@ -5581,29 +5495,29 @@ mod tests {
|
||||||
resolved_commit: None,
|
resolved_commit: None,
|
||||||
materialization_status: "present".to_string(),
|
materialization_status: "present".to_string(),
|
||||||
cleanliness: "unknown".to_string(),
|
cleanliness: "unknown".to_string(),
|
||||||
management_kind: "runtime_unmanaged".to_string(),
|
|
||||||
created_at: "1".to_string(),
|
created_at: "1".to_string(),
|
||||||
updated_at: "2".to_string(),
|
updated_at: "2".to_string(),
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let managed = working_directory_summaries(&api)
|
let summaries = working_directory_summaries(&api)
|
||||||
.unwrap_or_else(|err| panic!("working_directory_summaries failed: {}", err.error));
|
.unwrap_or_else(|err| panic!("working_directory_summaries failed: {}", err.error));
|
||||||
assert_eq!(managed.len(), 1);
|
let ids = summaries
|
||||||
assert_eq!(managed[0].working_directory_id, "managed");
|
.iter()
|
||||||
assert_eq!(
|
.map(|summary| summary.working_directory_id.as_str())
|
||||||
managed[0].management_kind.as_deref(),
|
.collect::<Vec<_>>();
|
||||||
Some("backend_managed")
|
assert!(ids.contains(&"managed"));
|
||||||
);
|
assert!(ids.contains(&"runtime-direct"));
|
||||||
|
|
||||||
let (runtime_projection, _) =
|
let (runtime_projection, _) =
|
||||||
runtime_working_directory_summaries(&api, EMBEDDED_WORKER_RUNTIME_ID).unwrap_or_else(
|
runtime_working_directory_summaries(&api, EMBEDDED_WORKER_RUNTIME_ID).unwrap_or_else(
|
||||||
|err| panic!("runtime_working_directory_summaries failed: {}", err.error),
|
|err| panic!("runtime_working_directory_summaries failed: {}", err.error),
|
||||||
);
|
);
|
||||||
assert!(runtime_projection.iter().any(|summary| {
|
assert!(
|
||||||
summary.working_directory_id == "runtime-direct"
|
runtime_projection
|
||||||
&& summary.management_kind.as_deref() == Some("runtime_unmanaged")
|
.iter()
|
||||||
}));
|
.any(|summary| summary.working_directory_id == "runtime-direct")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn unmanaged_runtime_workdir_projection_is_typed_and_diagnostic_safe() {
|
fn unmanaged_runtime_workdir_projection_is_typed_and_diagnostic_safe() {
|
||||||
|
|
@ -5616,7 +5530,6 @@ mod tests {
|
||||||
resolved_commit: None,
|
resolved_commit: None,
|
||||||
materialization_status: "present".to_string(),
|
materialization_status: "present".to_string(),
|
||||||
cleanliness: "unknown".to_string(),
|
cleanliness: "unknown".to_string(),
|
||||||
management_kind: "runtime_unmanaged".to_string(),
|
|
||||||
created_at: "1".to_string(),
|
created_at: "1".to_string(),
|
||||||
updated_at: "2".to_string(),
|
updated_at: "2".to_string(),
|
||||||
};
|
};
|
||||||
|
|
@ -5624,10 +5537,6 @@ mod tests {
|
||||||
let projected = workdir_summary_from_record(&workdir);
|
let projected = workdir_summary_from_record(&workdir);
|
||||||
|
|
||||||
assert_eq!(projected.status, WorkingDirectoryStatusKind::Active);
|
assert_eq!(projected.status, WorkingDirectoryStatusKind::Active);
|
||||||
assert_eq!(
|
|
||||||
projected.management_kind.as_deref(),
|
|
||||||
Some("runtime_unmanaged")
|
|
||||||
);
|
|
||||||
let serialized = serde_json::to_string(&projected).unwrap();
|
let serialized = serde_json::to_string(&projected).unwrap();
|
||||||
assert!(!serialized.contains("/tmp/"));
|
assert!(!serialized.contains("/tmp/"));
|
||||||
assert!(!serialized.contains("materialized_path"));
|
assert!(!serialized.contains("materialized_path"));
|
||||||
|
|
@ -6227,7 +6136,6 @@ mod tests {
|
||||||
workdir_id: workdir_id.to_string(),
|
workdir_id: workdir_id.to_string(),
|
||||||
runtime_id: "runtime-test".to_string(),
|
runtime_id: "runtime-test".to_string(),
|
||||||
repository_id: "repo-test".to_string(),
|
repository_id: "repo-test".to_string(),
|
||||||
management_kind: "backend_managed".to_string(),
|
|
||||||
selector: Some("HEAD".to_string()),
|
selector: Some("HEAD".to_string()),
|
||||||
resolved_commit: None,
|
resolved_commit: None,
|
||||||
materialization_status: status.to_string(),
|
materialization_status: status.to_string(),
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,11 @@ const MIGRATIONS: &[Migration] = &[
|
||||||
name: "add workdir runtime observation states",
|
name: "add workdir runtime observation states",
|
||||||
apply: add_workdir_runtime_observation_states,
|
apply: add_workdir_runtime_observation_states,
|
||||||
},
|
},
|
||||||
|
Migration {
|
||||||
|
version: 7,
|
||||||
|
name: "remove workdir registry management kind",
|
||||||
|
apply: remove_workdir_registry_management_kind_column,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
struct Migration {
|
struct Migration {
|
||||||
|
|
@ -91,8 +96,6 @@ pub struct WorkdirRegistryRecord {
|
||||||
pub resolved_commit: Option<String>,
|
pub resolved_commit: Option<String>,
|
||||||
pub materialization_status: String,
|
pub materialization_status: String,
|
||||||
pub cleanliness: String,
|
pub cleanliness: String,
|
||||||
/// `backend_managed` rows are authored by this Backend; `runtime_unmanaged` is for diagnostics only.
|
|
||||||
pub management_kind: String,
|
|
||||||
pub created_at: String,
|
pub created_at: String,
|
||||||
pub updated_at: String,
|
pub updated_at: String,
|
||||||
}
|
}
|
||||||
|
|
@ -152,11 +155,6 @@ pub trait ControlPlaneStore: Send + Sync {
|
||||||
workspace_id: &str,
|
workspace_id: &str,
|
||||||
limit: usize,
|
limit: usize,
|
||||||
) -> Result<Vec<WorkdirRegistryRecord>>;
|
) -> Result<Vec<WorkdirRegistryRecord>>;
|
||||||
fn list_managed_workdir_registry(
|
|
||||||
&self,
|
|
||||||
workspace_id: &str,
|
|
||||||
limit: usize,
|
|
||||||
) -> Result<Vec<WorkdirRegistryRecord>>;
|
|
||||||
fn delete_workdir_registry(&self, workspace_id: &str, workdir_id: &str) -> Result<bool>;
|
fn delete_workdir_registry(&self, workspace_id: &str, workdir_id: &str) -> Result<bool>;
|
||||||
|
|
||||||
fn upsert_worker_workdir_link(&self, record: &WorkerWorkdirLinkRecord) -> Result<()>;
|
fn upsert_worker_workdir_link(&self, record: &WorkerWorkdirLinkRecord) -> Result<()>;
|
||||||
|
|
@ -378,8 +376,8 @@ impl ControlPlaneStore for SqliteWorkspaceStore {
|
||||||
conn.execute(
|
conn.execute(
|
||||||
r#"INSERT INTO workdir_registry (
|
r#"INSERT INTO workdir_registry (
|
||||||
workspace_id, workdir_id, runtime_id, repository_id, selector, resolved_commit,
|
workspace_id, workdir_id, runtime_id, repository_id, selector, resolved_commit,
|
||||||
materialization_status, cleanliness, management_kind, created_at, updated_at
|
materialization_status, cleanliness, created_at, updated_at
|
||||||
) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)
|
) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)
|
||||||
ON CONFLICT(workspace_id, workdir_id) DO UPDATE SET
|
ON CONFLICT(workspace_id, workdir_id) DO UPDATE SET
|
||||||
runtime_id = excluded.runtime_id,
|
runtime_id = excluded.runtime_id,
|
||||||
repository_id = excluded.repository_id,
|
repository_id = excluded.repository_id,
|
||||||
|
|
@ -387,7 +385,6 @@ impl ControlPlaneStore for SqliteWorkspaceStore {
|
||||||
resolved_commit = excluded.resolved_commit,
|
resolved_commit = excluded.resolved_commit,
|
||||||
materialization_status = excluded.materialization_status,
|
materialization_status = excluded.materialization_status,
|
||||||
cleanliness = excluded.cleanliness,
|
cleanliness = excluded.cleanliness,
|
||||||
management_kind = excluded.management_kind,
|
|
||||||
updated_at = excluded.updated_at"#,
|
updated_at = excluded.updated_at"#,
|
||||||
params![
|
params![
|
||||||
record.workspace_id,
|
record.workspace_id,
|
||||||
|
|
@ -398,7 +395,6 @@ impl ControlPlaneStore for SqliteWorkspaceStore {
|
||||||
record.resolved_commit,
|
record.resolved_commit,
|
||||||
record.materialization_status,
|
record.materialization_status,
|
||||||
record.cleanliness,
|
record.cleanliness,
|
||||||
record.management_kind,
|
|
||||||
record.created_at,
|
record.created_at,
|
||||||
record.updated_at,
|
record.updated_at,
|
||||||
],
|
],
|
||||||
|
|
@ -442,22 +438,6 @@ impl ControlPlaneStore for SqliteWorkspaceStore {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list_managed_workdir_registry(
|
|
||||||
&self,
|
|
||||||
workspace_id: &str,
|
|
||||||
limit: usize,
|
|
||||||
) -> Result<Vec<WorkdirRegistryRecord>> {
|
|
||||||
self.with_conn(|conn| {
|
|
||||||
let sql = workdir_registry_select_sql(
|
|
||||||
"WHERE workspace_id = ?1 AND management_kind = 'backend_managed' ORDER BY updated_at DESC LIMIT ?2",
|
|
||||||
);
|
|
||||||
let mut stmt = conn.prepare(sql.as_str())?;
|
|
||||||
let rows = stmt.query_map(params![workspace_id, limit as i64], read_workdir_registry_record)?;
|
|
||||||
rows.collect::<std::result::Result<Vec<_>, _>>()
|
|
||||||
.map_err(Error::from)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn delete_workdir_registry(&self, workspace_id: &str, workdir_id: &str) -> Result<bool> {
|
fn delete_workdir_registry(&self, workspace_id: &str, workdir_id: &str) -> Result<bool> {
|
||||||
self.with_conn(|conn| {
|
self.with_conn(|conn| {
|
||||||
let changed = conn.execute(
|
let changed = conn.execute(
|
||||||
|
|
@ -577,7 +557,7 @@ fn read_worker_registry_record(row: &rusqlite::Row<'_>) -> rusqlite::Result<Work
|
||||||
fn workdir_registry_select_sql(where_clause: &str) -> String {
|
fn workdir_registry_select_sql(where_clause: &str) -> String {
|
||||||
format!(
|
format!(
|
||||||
"SELECT workspace_id, workdir_id, runtime_id, repository_id, selector, resolved_commit, \
|
"SELECT workspace_id, workdir_id, runtime_id, repository_id, selector, resolved_commit, \
|
||||||
materialization_status, cleanliness, management_kind, created_at, updated_at \
|
materialization_status, cleanliness, created_at, updated_at \
|
||||||
FROM workdir_registry {where_clause}"
|
FROM workdir_registry {where_clause}"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -594,9 +574,8 @@ fn read_workdir_registry_record(
|
||||||
resolved_commit: row.get(5)?,
|
resolved_commit: row.get(5)?,
|
||||||
materialization_status: row.get(6)?,
|
materialization_status: row.get(6)?,
|
||||||
cleanliness: row.get(7)?,
|
cleanliness: row.get(7)?,
|
||||||
management_kind: row.get(8)?,
|
created_at: row.get(8)?,
|
||||||
created_at: row.get(9)?,
|
updated_at: row.get(9)?,
|
||||||
updated_at: row.get(10)?,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -629,7 +608,6 @@ CREATE TABLE IF NOT EXISTS workdir_registry (
|
||||||
resolved_commit TEXT,
|
resolved_commit TEXT,
|
||||||
materialization_status TEXT NOT NULL CHECK (materialization_status IN ('pending', 'present', 'not_found', 'corrupted', 'unknown', 'failed')),
|
materialization_status TEXT NOT NULL CHECK (materialization_status IN ('pending', 'present', 'not_found', 'corrupted', 'unknown', 'failed')),
|
||||||
cleanliness TEXT NOT NULL CHECK (cleanliness IN ('clean', 'dirty', 'unknown')),
|
cleanliness TEXT NOT NULL CHECK (cleanliness IN ('clean', 'dirty', 'unknown')),
|
||||||
management_kind TEXT NOT NULL CHECK (management_kind IN ('backend_managed', 'runtime_unmanaged')),
|
|
||||||
created_at TEXT NOT NULL,
|
created_at TEXT NOT NULL,
|
||||||
updated_at TEXT NOT NULL,
|
updated_at TEXT NOT NULL,
|
||||||
PRIMARY KEY (workspace_id, workdir_id),
|
PRIMARY KEY (workspace_id, workdir_id),
|
||||||
|
|
@ -948,7 +926,6 @@ fn add_workdir_runtime_observation_states(conn: &Connection) -> Result<()> {
|
||||||
resolved_commit TEXT,
|
resolved_commit TEXT,
|
||||||
materialization_status TEXT NOT NULL CHECK (materialization_status IN ('pending', 'present', 'not_found', 'corrupted', 'unknown', 'failed')),
|
materialization_status TEXT NOT NULL CHECK (materialization_status IN ('pending', 'present', 'not_found', 'corrupted', 'unknown', 'failed')),
|
||||||
cleanliness TEXT NOT NULL CHECK (cleanliness IN ('clean', 'dirty', 'unknown')),
|
cleanliness TEXT NOT NULL CHECK (cleanliness IN ('clean', 'dirty', 'unknown')),
|
||||||
management_kind TEXT NOT NULL CHECK (management_kind IN ('backend_managed', 'runtime_unmanaged')),
|
|
||||||
created_at TEXT NOT NULL,
|
created_at TEXT NOT NULL,
|
||||||
updated_at TEXT NOT NULL,
|
updated_at TEXT NOT NULL,
|
||||||
PRIMARY KEY (workspace_id, workdir_id),
|
PRIMARY KEY (workspace_id, workdir_id),
|
||||||
|
|
@ -956,7 +933,7 @@ fn add_workdir_runtime_observation_states(conn: &Connection) -> Result<()> {
|
||||||
);
|
);
|
||||||
INSERT OR REPLACE INTO workdir_registry_v6 (
|
INSERT OR REPLACE INTO workdir_registry_v6 (
|
||||||
workspace_id, workdir_id, runtime_id, repository_id, selector, resolved_commit,
|
workspace_id, workdir_id, runtime_id, repository_id, selector, resolved_commit,
|
||||||
materialization_status, cleanliness, management_kind, created_at, updated_at
|
materialization_status, cleanliness, created_at, updated_at
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
workspace_id, workdir_id, runtime_id, repository_id, selector, resolved_commit,
|
workspace_id, workdir_id, runtime_id, repository_id, selector, resolved_commit,
|
||||||
|
|
@ -965,7 +942,7 @@ fn add_workdir_runtime_observation_states(conn: &Connection) -> Result<()> {
|
||||||
WHEN 'removed' THEN 'not_found'
|
WHEN 'removed' THEN 'not_found'
|
||||||
ELSE materialization_status
|
ELSE materialization_status
|
||||||
END,
|
END,
|
||||||
cleanliness, management_kind, created_at, updated_at
|
cleanliness, created_at, updated_at
|
||||||
FROM workdir_registry;
|
FROM workdir_registry;
|
||||||
DROP TABLE workdir_registry;
|
DROP TABLE workdir_registry;
|
||||||
ALTER TABLE workdir_registry_v6 RENAME TO workdir_registry;
|
ALTER TABLE workdir_registry_v6 RENAME TO workdir_registry;
|
||||||
|
|
@ -976,6 +953,48 @@ fn add_workdir_runtime_observation_states(conn: &Connection) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn remove_workdir_registry_management_kind_column(conn: &Connection) -> Result<()> {
|
||||||
|
if !table_exists(conn, "workdir_registry")?
|
||||||
|
|| !table_columns(conn, "workdir_registry")?
|
||||||
|
.iter()
|
||||||
|
.any(|column| column == "management_kind")
|
||||||
|
{
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.execute_batch(
|
||||||
|
r#"
|
||||||
|
CREATE TABLE workdir_registry_v7 (
|
||||||
|
workspace_id TEXT NOT NULL,
|
||||||
|
workdir_id TEXT NOT NULL,
|
||||||
|
runtime_id TEXT NOT NULL,
|
||||||
|
repository_id TEXT NOT NULL,
|
||||||
|
selector TEXT,
|
||||||
|
resolved_commit TEXT,
|
||||||
|
materialization_status TEXT NOT NULL CHECK (materialization_status IN ('pending', 'present', 'not_found', 'corrupted', 'unknown', 'failed')),
|
||||||
|
cleanliness TEXT NOT NULL CHECK (cleanliness IN ('clean', 'dirty', 'unknown')),
|
||||||
|
created_at TEXT NOT NULL,
|
||||||
|
updated_at TEXT NOT NULL,
|
||||||
|
PRIMARY KEY (workspace_id, workdir_id),
|
||||||
|
FOREIGN KEY (workspace_id) REFERENCES workspaces(workspace_id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
INSERT OR REPLACE INTO workdir_registry_v7 (
|
||||||
|
workspace_id, workdir_id, runtime_id, repository_id, selector, resolved_commit,
|
||||||
|
materialization_status, cleanliness, created_at, updated_at
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
workspace_id, workdir_id, runtime_id, repository_id, selector, resolved_commit,
|
||||||
|
materialization_status, cleanliness, created_at, updated_at
|
||||||
|
FROM workdir_registry;
|
||||||
|
DROP TABLE workdir_registry;
|
||||||
|
ALTER TABLE workdir_registry_v7 RENAME TO workdir_registry;
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_workdir_registry_workspace_updated
|
||||||
|
ON workdir_registry(workspace_id, updated_at DESC);
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn create_schema_v0_tables(conn: &Connection) -> Result<()> {
|
fn create_schema_v0_tables(conn: &Connection) -> Result<()> {
|
||||||
conn.execute_batch(
|
conn.execute_batch(
|
||||||
r#"
|
r#"
|
||||||
|
|
@ -1199,7 +1218,7 @@ mod tests {
|
||||||
let db = dir.path().join("control-plane.sqlite");
|
let db = dir.path().join("control-plane.sqlite");
|
||||||
let store = SqliteWorkspaceStore::open(&db).unwrap();
|
let store = SqliteWorkspaceStore::open(&db).unwrap();
|
||||||
|
|
||||||
assert_eq!(store.schema_version().await.unwrap(), 6);
|
assert_eq!(store.schema_version().await.unwrap(), 7);
|
||||||
|
|
||||||
let record = WorkspaceRecord {
|
let record = WorkspaceRecord {
|
||||||
workspace_id: "local-dev".to_string(),
|
workspace_id: "local-dev".to_string(),
|
||||||
|
|
@ -1211,7 +1230,7 @@ mod tests {
|
||||||
store.upsert_workspace(&record).await.unwrap();
|
store.upsert_workspace(&record).await.unwrap();
|
||||||
|
|
||||||
let reopened = SqliteWorkspaceStore::open(&db).unwrap();
|
let reopened = SqliteWorkspaceStore::open(&db).unwrap();
|
||||||
assert_eq!(reopened.schema_version().await.unwrap(), 6);
|
assert_eq!(reopened.schema_version().await.unwrap(), 7);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
reopened.get_workspace("local-dev").await.unwrap(),
|
reopened.get_workspace("local-dev").await.unwrap(),
|
||||||
Some(record)
|
Some(record)
|
||||||
|
|
@ -1420,7 +1439,7 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let store = SqliteWorkspaceStore::from_connection(conn).unwrap();
|
let store = SqliteWorkspaceStore::from_connection(conn).unwrap();
|
||||||
assert_eq!(store.schema_version().await.unwrap(), 6);
|
assert_eq!(store.schema_version().await.unwrap(), 7);
|
||||||
|
|
||||||
store
|
store
|
||||||
.with_conn(|conn| {
|
.with_conn(|conn| {
|
||||||
|
|
@ -1550,7 +1569,6 @@ mod tests {
|
||||||
resolved_commit: Some("abcdef".to_string()),
|
resolved_commit: Some("abcdef".to_string()),
|
||||||
materialization_status: "not_found".to_string(),
|
materialization_status: "not_found".to_string(),
|
||||||
cleanliness: "clean".to_string(),
|
cleanliness: "clean".to_string(),
|
||||||
management_kind: "backend_managed".to_string(),
|
|
||||||
created_at: "2".to_string(),
|
created_at: "2".to_string(),
|
||||||
updated_at: "3".to_string(),
|
updated_at: "3".to_string(),
|
||||||
};
|
};
|
||||||
|
|
@ -1564,7 +1582,6 @@ mod tests {
|
||||||
resolved_commit: Some("123456".to_string()),
|
resolved_commit: Some("123456".to_string()),
|
||||||
materialization_status: "present".to_string(),
|
materialization_status: "present".to_string(),
|
||||||
cleanliness: "unknown".to_string(),
|
cleanliness: "unknown".to_string(),
|
||||||
management_kind: "runtime_unmanaged".to_string(),
|
|
||||||
created_at: "3".to_string(),
|
created_at: "3".to_string(),
|
||||||
updated_at: "4".to_string(),
|
updated_at: "4".to_string(),
|
||||||
};
|
};
|
||||||
|
|
@ -1597,12 +1614,6 @@ mod tests {
|
||||||
store.list_workdir_registry("local-dev", 10).unwrap(),
|
store.list_workdir_registry("local-dev", 10).unwrap(),
|
||||||
vec![unmanaged_workdir.clone(), workdir.clone()]
|
vec![unmanaged_workdir.clone(), workdir.clone()]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
|
||||||
store
|
|
||||||
.list_managed_workdir_registry("local-dev", 10)
|
|
||||||
.unwrap(),
|
|
||||||
vec![workdir]
|
|
||||||
);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
store
|
store
|
||||||
.list_worker_workdir_links("local-dev", "embedded", 1)
|
.list_worker_workdir_links("local-dev", "embedded", 1)
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,6 @@ export type WorkingDirectorySummary = {
|
||||||
status: string;
|
status: string;
|
||||||
cleanliness?: string | null;
|
cleanliness?: string | null;
|
||||||
primary_worker_id?: number | null;
|
primary_worker_id?: number | null;
|
||||||
management_kind?: "backend_managed" | "runtime_unmanaged" | string | null;
|
|
||||||
cleanup_target: {
|
cleanup_target: {
|
||||||
kind: string;
|
kind: string;
|
||||||
working_directory_id: string;
|
working_directory_id: string;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user