Simplify build.sh and update run.sh for self-contained execution

- Simplified build.sh to just build in release mode with warning suppression
- Updated run.sh to build first, then start supervisor and admin UI together
- Run script now starts both supervisor API and admin UI in background
- Added proper cleanup handler for graceful shutdown
- Removed admin UI compilation errors by fixing JsValue handling
- Added list_jobs method to WASM client for admin UI compatibility
This commit is contained in:
Timur Gordon
2025-11-04 17:05:01 +01:00
parent 3356a03895
commit b8ef14d06c
14 changed files with 424 additions and 7522 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -327,28 +327,38 @@ impl Component for App {
spawn_local(async move {
match client.list_jobs().await {
Ok(mut jobs) => {
// Fetch status for each job from Redis
for job in &mut jobs {
if let Some(job_id) = job.get("id").and_then(|v| v.as_str()) {
match client.get_job_status(job_id).await {
Ok(status_response) => {
if let Some(status) = status_response.get("status").and_then(|v| v.as_str()) {
if let Some(obj) = job.as_object_mut() {
obj.insert("status".to_string(), serde_json::Value::String(status.to_string()));
Ok(jobs_js) => {
// Convert JsValue to Vec<serde_json::Value>
match serde_wasm_bindgen::from_value::<Vec<serde_json::Value>>(jobs_js) {
Ok(mut jobs) => {
// Fetch status for each job from Redis
for job in &mut jobs {
if let Some(job_id) = job.get("id").and_then(|v| v.as_str()) {
match client.get_job_status(job_id).await {
Ok(status_response) => {
if let Ok(status_obj) = serde_wasm_bindgen::from_value::<serde_json::Value>(status_response) {
if let Some(status) = status_obj.get("status").and_then(|v| v.as_str()) {
if let Some(obj) = job.as_object_mut() {
obj.insert("status".to_string(), serde_json::Value::String(status.to_string()));
}
}
}
}
Err(_) => {
// Job not found in Redis, likely not started yet
if let Some(obj) = job.as_object_mut() {
obj.insert("status".to_string(), serde_json::Value::String("queued".to_string()));
}
}
}
}
Err(_) => {
// Job not found in Redis, likely not started yet
if let Some(obj) = job.as_object_mut() {
obj.insert("status".to_string(), serde_json::Value::String("queued".to_string()));
}
}
}
link.send_message(Msg::JobsLoaded(Ok(jobs)));
}
Err(e) => {
link.send_message(Msg::JobsLoaded(Err(format!("Failed to parse jobs: {}", e))));
}
}
link.send_message(Msg::JobsLoaded(Ok(jobs)));
}
Err(e) => {
link.send_message(Msg::JobsLoaded(Err(format!("{:?}", e))));
@@ -801,8 +811,10 @@ impl Component for App {
spawn_local(async move {
match client.get_job_status(&job_id_clone).await {
Ok(status_response) => {
if let Some(status) = status_response.get("status").and_then(|v| v.as_str()) {
link.send_message(Msg::JobStatusUpdated(job_id_clone, status.to_string()));
if let Ok(status_obj) = serde_wasm_bindgen::from_value::<serde_json::Value>(status_response) {
if let Some(status) = status_obj.get("status").and_then(|v| v.as_str()) {
link.send_message(Msg::JobStatusUpdated(job_id_clone, status.to_string()));
}
}
}
Err(e) => {
@@ -884,10 +896,14 @@ impl Component for App {
match client.get_job_result(&job_id).await {
Ok(result) => {
// Extract the result string from the response
let output = if let Some(result_str) = result.get("result").and_then(|v| v.as_str()) {
result_str.to_string()
let output = if let Ok(result_obj) = serde_wasm_bindgen::from_value::<serde_json::Value>(result.clone()) {
if let Some(result_str) = result_obj.get("result").and_then(|v| v.as_str()) {
result_str.to_string()
} else {
format!("{:?}", result_obj)
}
} else {
format!("{}", result)
format!("{:?}", result)
};
link.send_message(Msg::JobOutputLoaded(Ok(output)));
}
@@ -899,6 +915,36 @@ impl Component for App {
}
true
}
Msg::ViewJobLogs(job_id) => {
log::info!("View logs for job: {}", job_id);
self.viewing_job_output = Some(job_id.clone());
self.job_output = None; // Clear previous output
if let Some(client) = &self.client {
let client = client.clone();
let link = ctx.link().clone();
spawn_local(async move {
match client.get_job_logs(&job_id, Some(1000)).await {
Ok(logs_js) => {
// Convert JsValue to Vec<String>
match serde_wasm_bindgen::from_value::<Vec<String>>(logs_js) {
Ok(logs) => {
link.send_message(Msg::JobLogsLoaded(Ok(logs)));
}
Err(e) => {
link.send_message(Msg::JobLogsLoaded(Err(format!("Failed to parse logs: {}", e))));
}
}
}
Err(e) => {
link.send_message(Msg::JobLogsLoaded(Err(format!("{:?}", e))));
}
}
});
}
true
}
Msg::JobOutputLoaded(result) => {
match result {
Ok(output) => {
@@ -967,10 +1013,14 @@ impl Component for App {
spawn_local(async move {
match client_output.get_job_result(&job_id_output).await {
Ok(result) => {
let output = if let Some(result_str) = result.get("result").and_then(|v| v.as_str()) {
result_str.to_string()
let output = if let Ok(result_obj) = serde_wasm_bindgen::from_value::<serde_json::Value>(result.clone()) {
if let Some(result_str) = result_obj.get("result").and_then(|v| v.as_str()) {
result_str.to_string()
} else {
format!("{:?}", result_obj)
}
} else {
format!("{}", result)
format!("{:?}", result)
};
link_output.send_message(Msg::JobOutputLoaded(Ok(output)));
}
@@ -1019,10 +1069,14 @@ impl Component for App {
spawn_local(async move {
match client_output.get_job_result(&job_id_output).await {
Ok(result) => {
let output = if let Some(result_str) = result.get("result").and_then(|v| v.as_str()) {
result_str.to_string()
let output = if let Ok(result_obj) = serde_wasm_bindgen::from_value::<serde_json::Value>(result.clone()) {
if let Some(result_str) = result_obj.get("result").and_then(|v| v.as_str()) {
result_str.to_string()
} else {
format!("{:?}", result_obj)
}
} else {
format!("{}", result)
format!("{:?}", result)
};
link_output.send_message(Msg::JobOutputLoaded(Ok(output)));
}
@@ -1948,6 +2002,7 @@ impl App {
let created_at = job.get("created_at").and_then(|v| v.as_str()).unwrap_or("");
let signatures = job.get("signatures").and_then(|v| v.as_array()).map(|a| a.len()).unwrap_or(0);
#[allow(unused_variables)]
let status_class = match status {
"created" => "status-created",
"dispatched" | "queued" => "status-queued",
@@ -2337,8 +2392,8 @@ impl App {
{
if let Some(job) = job {
let payload = job.get("payload").and_then(|v| v.as_str()).unwrap_or("");
let runner = job.get("runner").and_then(|v| v.as_str()).unwrap_or("");
let timeout = job.get("timeout").and_then(|v| v.as_u64()).unwrap_or(0);
let _runner = job.get("runner").and_then(|v| v.as_str()).unwrap_or("");
let _timeout = job.get("timeout").and_then(|v| v.as_u64()).unwrap_or(0);
let status = job.get("status").and_then(|v| v.as_str()).unwrap_or("unknown");
let status_class = match status {