feat: add retained Worker session observation

This commit is contained in:
2026-09-18 05:53:53 +09:00
30 changed files with 1277 additions and 128 deletions
+1
View File
@@ -24,6 +24,7 @@ flow = { path = "../flow" }
manifest.workspace = true
protocol = { workspace = true }
runtime-api.workspace = true
server-api.workspace = true
project-record.workspace = true
reqwest = { version = "0.13", default-features = false, features = ["blocking", "json", "native-tls"] }
ring.workspace = true
+62
View File
@@ -1132,6 +1132,17 @@ pub trait WorkspaceWorkerRuntime: Send + Sync {
))
}
fn worker_session(
&self,
_workspace_id: &str,
_worker_ref: &EmbeddedWorkerRef,
) -> Result<runtime_api::WorkerSessionAvailability, String> {
Ok(runtime_api::WorkerSessionAvailability::Unavailable {
reason: runtime_api::WorkerSessionUnavailableReason::StorageUnavailable,
message: "retained session storage is unavailable".to_string(),
})
}
fn observation_source(
&self,
_worker_id: &str,
@@ -1922,6 +1933,29 @@ impl RuntimeRegistry {
})
}
pub fn worker_session(
&self,
workspace_id: &str,
worker: &RuntimeWorkerRef,
) -> Result<runtime_api::WorkerSessionAvailability, RuntimeRegistryError> {
validate_backend_identifier("runtime_id", &worker.runtime_id)?;
validate_backend_identifier("worker_id", &worker.worker_id)?;
let runtime = self.runtime(&worker.runtime_id)?;
let worker_ref =
EmbeddedWorkerRef::new(EmbeddedWorkerId::parse(&worker.worker_id).ok_or_else(
|| RuntimeRegistryError::UnknownWorker {
worker: worker.clone(),
},
)?);
runtime
.worker_session(workspace_id, &worker_ref)
.map_err(|message| RuntimeRegistryError::RuntimeOperationFailed {
runtime_id: worker.runtime_id.clone(),
code: "worker_session_observation_failed".to_string(),
message,
})
}
pub fn observation_source(
&self,
worker: &RuntimeWorkerRef,
@@ -2773,6 +2807,17 @@ impl WorkspaceWorkerRuntime for EmbeddedWorkerRuntime {
.map_err(|error| error.to_string())
}
fn worker_session(
&self,
workspace_id: &str,
worker_ref: &EmbeddedWorkerRef,
) -> Result<runtime_api::WorkerSessionAvailability, String> {
let scope = RuntimeWorkspaceScope::new(workspace_id, "embedded-backend");
self.runtime
.worker_session_scoped(&scope, worker_ref)
.map_err(|error| error.to_string())
}
fn observation_source(
&self,
worker_id: &str,
@@ -4712,6 +4757,23 @@ impl WorkspaceWorkerRuntime for RemoteWorkerRuntime {
.map_err(|diagnostic| diagnostic.message)
}
fn worker_session(
&self,
workspace_id: &str,
worker_ref: &EmbeddedWorkerRef,
) -> Result<runtime_api::WorkerSessionAvailability, String> {
let worker_id = worker_ref.worker_id.to_string();
let request = runtime_api::WorkerSessionRequest {
workspace_id: workspace_id.to_string(),
};
self.run_runtime_api(
self.request_timeout,
MAX_REMOTE_RUNTIME_RESPONSE_BYTES,
move |client| async move { client.worker_session(worker_id, request).await },
)
.map_err(|diagnostic| diagnostic.message)
}
fn observation_source(
&self,
worker_id: &str,
+39
View File
@@ -3040,6 +3040,42 @@ fn build_server_auth_router(api: ServerAuthApi) -> Router {
.with_state(api)
}
impl server_api::ServerApi for WorkspaceApi {
async fn worker_session(
&self,
workspace_id: String,
runtime_id: String,
worker_id: String,
) -> std::result::Result<server_api::WorkspaceWorkerSessionResponse, server_api::ServerApiError>
{
if workspace_id != self.config.workspace_id {
return Err(runtime_api::RuntimeApiError::new(
StatusCode::NOT_FOUND.as_u16(),
"workspace_not_found",
"Workspace was not found",
));
}
let worker = RuntimeWorkerRef::new(runtime_id.clone(), worker_id.clone());
let observation = self
.runtime
.worker_session(&workspace_id, &worker)
.map_err(|_error| {
runtime_api::RuntimeApiError::new(
StatusCode::BAD_GATEWAY.as_u16(),
"worker_session_observation_failed",
"Worker Session observation failed",
)
})?;
Ok(server_api::WorkspaceWorkerSessionResponse {
subject: workspace_api::WorkspaceWorkerSubject::RuntimeWorker {
runtime_id,
worker_id,
},
observation,
})
}
}
fn build_inner_router(api: WorkspaceApi) -> Router {
let auth = build_server_auth_router(ServerAuthApi::from(&api));
let scoped_ticket_relations_query_path =
@@ -3632,6 +3668,9 @@ fn build_inner_router(api: WorkspaceApi) -> Router {
"/api/w/{workspace_id}/hosts/{host_id}/workers",
get(scoped_list_host_workers),
)
.merge(
server_api::ServerApiAxum::router(api.clone()).with_state::<WorkspaceApi>(()),
)
.fallback(get(static_or_spa_fallback))
.with_state(api);
auth.merge(workspace)