workspace: use opaque numeric worker ids
This commit is contained in:
@@ -366,7 +366,7 @@ impl FsRuntimeStore {
|
||||
fn worker_dir(&self, worker_id: &WorkerId) -> PathBuf {
|
||||
self.runtime_dir
|
||||
.join(WORKERS_DIR)
|
||||
.join(encoded_component(worker_id.as_str()))
|
||||
.join(encoded_component(&worker_id.to_string()))
|
||||
}
|
||||
|
||||
#[cfg(feature = "ws-server")]
|
||||
|
||||
@@ -692,11 +692,11 @@ async fn cancel_worker(
|
||||
}
|
||||
|
||||
fn worker_ref_for(runtime: &Runtime, worker_id: String) -> Result<WorkerRef, RuntimeHttpRestError> {
|
||||
let worker_id = WorkerId::new(worker_id).ok_or_else(|| {
|
||||
let worker_id = WorkerId::parse(&worker_id).ok_or_else(|| {
|
||||
RuntimeHttpRestError::new(
|
||||
StatusCode::BAD_REQUEST,
|
||||
"invalid_worker_id",
|
||||
"worker_id must not be empty",
|
||||
"worker_id must be an unsigned integer",
|
||||
)
|
||||
})?;
|
||||
let runtime_id = runtime
|
||||
@@ -1107,12 +1107,12 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn runtime_errors_use_typed_rest_error_shape() {
|
||||
let app = runtime_http_router(Runtime::new_memory(), None);
|
||||
let response = empty_request(app, Method::GET, "/v1/workers/worker-missing").await;
|
||||
let response = empty_request(app, Method::GET, "/v1/workers/999").await;
|
||||
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
let error: RuntimeHttpErrorResponse = read_json(response).await;
|
||||
assert_eq!(error.error.code, "worker_not_found");
|
||||
assert!(error.error.message.contains("worker-missing"));
|
||||
assert!(error.error.message.contains("999"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,26 +36,25 @@ impl fmt::Display for RuntimeId {
|
||||
}
|
||||
|
||||
/// Runtime-local Worker identity.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct WorkerId(String);
|
||||
pub struct WorkerId(u64);
|
||||
|
||||
impl WorkerId {
|
||||
pub fn new(value: impl Into<String>) -> Option<Self> {
|
||||
let value = value.into();
|
||||
if value.trim().is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(Self(value))
|
||||
}
|
||||
pub fn new(value: u64) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
|
||||
pub fn parse(value: &str) -> Option<Self> {
|
||||
value.parse::<u64>().ok().map(Self)
|
||||
}
|
||||
|
||||
pub(crate) fn generated(sequence: u64) -> Self {
|
||||
Self(format!("worker-{sequence:08x}"))
|
||||
Self(sequence)
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self.0
|
||||
pub fn as_u64(&self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ pub fn build_profile_source_archive_fetch_request(
|
||||
BackendResourceFetchRequest {
|
||||
handle,
|
||||
runtime_id: runtime_id.as_str().to_string(),
|
||||
worker_id: worker_id.map(|id| id.as_str().to_string()),
|
||||
worker_id: worker_id.map(|id| id.to_string()),
|
||||
audit_correlation_id,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1122,13 +1122,11 @@ mod tests {
|
||||
#[test]
|
||||
fn runtime_worker_name_is_namespaced_by_runtime_id() {
|
||||
let runtime_id = RuntimeId::new("arc:remote".to_string()).unwrap();
|
||||
let worker_ref = crate::identity::WorkerRef::new(
|
||||
runtime_id,
|
||||
crate::identity::WorkerId::new("worker-00000001".to_string()).unwrap(),
|
||||
);
|
||||
let worker_ref =
|
||||
crate::identity::WorkerRef::new(runtime_id, crate::identity::WorkerId::new(1));
|
||||
let request = WorkerExecutionSpawnRequest {
|
||||
worker_ref: worker_ref.clone(),
|
||||
request: create_request("worker-00000001"),
|
||||
request: create_request("1"),
|
||||
context: WorkerExecutionContext::new(worker_ref, Arc::new(|_, _| panic!("unused"))),
|
||||
working_directory: None,
|
||||
config_bundle: None,
|
||||
@@ -1136,11 +1134,11 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
ProfileRuntimeWorkerFactory::runtime_worker_name(&request),
|
||||
"runtime-arc-remote-worker-00000001"
|
||||
"runtime-arc-remote-1"
|
||||
);
|
||||
assert_ne!(
|
||||
ProfileRuntimeWorkerFactory::runtime_worker_name(&request),
|
||||
"worker-00000001"
|
||||
"00000001"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -167,13 +167,8 @@ impl LocalGitWorktreeMaterializer {
|
||||
&self.runtime_root
|
||||
}
|
||||
|
||||
fn working_directory_id(worker_ref: &WorkerRef, repository_id: &str) -> String {
|
||||
format!(
|
||||
"{}-{}-{}",
|
||||
sanitize_path_component(worker_ref.runtime_id.as_str()),
|
||||
sanitize_path_component(worker_ref.worker_id.as_str()),
|
||||
sanitize_path_component(repository_id)
|
||||
)
|
||||
fn working_directory_id(_worker_ref: &WorkerRef, repository_id: &str) -> String {
|
||||
next_working_directory_id(repository_id)
|
||||
}
|
||||
|
||||
fn working_directory_root(&self, working_directory_id: &str) -> PathBuf {
|
||||
@@ -609,16 +604,13 @@ fn sanitize_path_component(value: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
fn next_working_directory_id(repository_id: &str) -> String {
|
||||
fn next_working_directory_id(_repository_id: &str) -> String {
|
||||
let now = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map(|duration| duration.as_millis())
|
||||
.map(|duration| duration.as_millis() as u64)
|
||||
.unwrap_or_default();
|
||||
let sequence = NEXT_WORKING_DIRECTORY_SEQUENCE.fetch_add(1, Ordering::Relaxed);
|
||||
format!(
|
||||
"alloc-{now}-{sequence}-{}",
|
||||
sanitize_path_component(repository_id)
|
||||
)
|
||||
let sequence = NEXT_WORKING_DIRECTORY_SEQUENCE.fetch_add(1, Ordering::Relaxed) & 0x00ff_ffff;
|
||||
format!("{now:013x}{sequence:06x}")
|
||||
}
|
||||
|
||||
fn validate_working_directory_id(
|
||||
|
||||
Reference in New Issue
Block a user