diff --git a/container-runtime/src/Adapters/HostSystemStartOs.ts b/container-runtime/src/Adapters/HostSystemStartOs.ts index ec4fac796..e863b6714 100644 --- a/container-runtime/src/Adapters/HostSystemStartOs.ts +++ b/container-runtime/src/Adapters/HostSystemStartOs.ts @@ -268,6 +268,7 @@ export class HostSystemStartOs implements Effects { > } setHealth(...[options]: Parameters) { + console.error("BLUJ sethealth", options) return this.rpcRound("setHealth", options) as ReturnType< T.Effects["setHealth"] > diff --git a/container-runtime/src/Adapters/Systems/SystemForEmbassy/MainLoop.ts b/container-runtime/src/Adapters/Systems/SystemForEmbassy/MainLoop.ts index daf3ade70..8142a17df 100644 --- a/container-runtime/src/Adapters/Systems/SystemForEmbassy/MainLoop.ts +++ b/container-runtime/src/Adapters/Systems/SystemForEmbassy/MainLoop.ts @@ -106,46 +106,106 @@ export class MainLoop { const { manifest } = this.system const effects = this.effects const start = Date.now() - return Object.values(manifest["health-checks"]).map((value) => { - const name = value.name - const interval = setInterval(async () => { - const actionProcedure = value - const timeChanged = Date.now() - start - if (actionProcedure.type === "docker") { - const container = await DockerProcedureContainer.of( - effects, - actionProcedure, - manifest.volumes, - ) - const executed = await container.exec([ - actionProcedure.entrypoint, - ...actionProcedure.args, - JSON.stringify(timeChanged), - ]) - const stderr = executed.stderr.toString() - if (stderr) - console.error(`Error running health check ${value.name}: ${stderr}`) - return executed.stdout.toString() - } else { - const moduleCode = await this.system.moduleCode - const method = moduleCode.health?.[value.name] - if (!method) - return console.error( - `Expecting that thejs health check ${value.name} exists`, + return Object.entries(manifest["health-checks"]).map( + ([healthId, value]) => { + const interval = setInterval(async () => { + const actionProcedure = value + const timeChanged = Date.now() - start + if (actionProcedure.type === "docker") { + const container = await DockerProcedureContainer.of( + effects, + actionProcedure, + manifest.volumes, ) - return (await method( - new PolyfillEffects(effects, this.system.manifest), - timeChanged, - ).then((x) => { - if ("result" in x) return x.result - if ("error" in x) - return console.error("Error getting config: " + x.error) - return console.error("Error getting config: " + x["error-code"][1]) - })) as any - } - }, EMBASSY_HEALTH_INTERVAL) + const executed = await container.exec([ + actionProcedure.entrypoint, + ...actionProcedure.args, + JSON.stringify(timeChanged), + ]) + const stderr = executed.stderr.toString() + if (stderr) + console.error( + `Error running health check ${value.name}: ${stderr}`, + ) + return executed.stdout.toString() + } else { + actionProcedure + const moduleCode = await this.system.moduleCode + const method = moduleCode.health?.[healthId] + if (!method) { + await effects.setHealth({ + name: healthId, + status: "failure", + message: `Expecting that thejs health check ${healthId} exists`, + }) + return + } - return { name, interval } - }) + const result = await method( + new PolyfillEffects(effects, this.system.manifest), + timeChanged, + ) + + if ("result" in result) { + await effects.setHealth({ + name: healthId, + status: "passing", + }) + return + } + if ("error" in result) { + await effects.setHealth({ + name: healthId, + status: "failure", + message: result.error, + }) + return + } + if (!("error-code" in result)) { + await effects.setHealth({ + name: healthId, + status: "failure", + message: `Unknown error type ${JSON.stringify(result)}`, + }) + return + } + const [code, message] = result["error-code"] + if (code === 59) { + await effects.setHealth({ + name: healthId, + status: "disabled", + message, + }) + return + } + if (code === 60) { + await effects.setHealth({ + name: healthId, + status: "starting", + message, + }) + return + } + if (code === 61) { + await effects.setHealth({ + name: healthId, + status: "warning", + message, + }) + return + } + + await effects.setHealth({ + name: healthId, + status: "failure", + message: `${result["error-code"][0]}: ${result["error-code"][1]}`, + }) + return + } + }, EMBASSY_HEALTH_INTERVAL) + + return { name: healthId, interval } + }, + ) } } diff --git a/core/startos/src/service/service_effect_handler.rs b/core/startos/src/service/service_effect_handler.rs index 55bc07916..369c8f319 100644 --- a/core/startos/src/service/service_effect_handler.rs +++ b/core/startos/src/service/service_effect_handler.rs @@ -13,7 +13,6 @@ use patch_db::json_ptr::JsonPointer; use rpc_toolkit::{from_fn, from_fn_async, AnyContext, Context, Empty, HandlerExt, ParentHandler}; use tokio::process::Command; -use crate::disk::mount::filesystem::idmapped::IdMapped; use crate::disk::mount::filesystem::loop_dev::LoopDev; use crate::disk::mount::filesystem::overlayfs::OverlayGuard; use crate::prelude::*; @@ -26,6 +25,7 @@ use crate::status::MainStatus; use crate::util::clap::FromStrParser; use crate::util::{new_guid, Invoke}; use crate::{db::model::ExposedUI, service::RunningStatus}; +use crate::{disk::mount::filesystem::idmapped::IdMapped, status::health_check::HealthCheckString}; use crate::{echo, ARCH}; #[derive(Clone)] @@ -605,30 +605,22 @@ async fn set_main_status(context: EffectContext, params: SetMainStatus) -> Resul #[serde(rename_all = "camelCase")] struct SetHealth { name: HealthCheckId, - health_result: Option, + status: HealthCheckString, + message: Option, } -async fn set_health(context: EffectContext, params: SetHealth) -> Result { +async fn set_health( + context: EffectContext, + SetHealth { + name, + status, + message, + }: SetHealth, +) -> Result { + dbg!(&name); + dbg!(&status); + dbg!(&message); let context = context.deref()?; - // TODO DrBonez + BLU-J Need to change the type from - // ```rs - // #[serde(tag = "result")] - // pub enum HealthCheckResult { - // Success, - // Disabled, - // Starting, - // Loading { message: String }, - // Failure { error: String }, - // } - // ``` - // to - // ```ts - // setHealth(o: { - // name: string - // status: HealthStatus - // message?: string - // }): Promise - // ``` let package_id = &context.id; context @@ -648,14 +640,22 @@ async fn set_health(context: EffectContext, params: SetHealth) -> Result { - health.remove(¶ms.name); - if let SetHealth { + health.remove(&name); + + health.insert( name, - health_result: Some(health_result), - } = params - { - health.insert(name, health_result); - } + match status { + HealthCheckString::Disabled => HealthCheckResult::Disabled, + HealthCheckString::Passing => HealthCheckResult::Success, + HealthCheckString::Starting => HealthCheckResult::Starting, + HealthCheckString::Warning => HealthCheckResult::Loading { + message: message.unwrap_or_default(), + }, + HealthCheckString::Failure => HealthCheckResult::Failure { + error: message.unwrap_or_default(), + }, + }, + ); } _ => return Ok(()), }; diff --git a/core/startos/src/status/health_check.rs b/core/startos/src/status/health_check.rs index 8189454c7..fef879e33 100644 --- a/core/startos/src/status/health_check.rs +++ b/core/startos/src/status/health_check.rs @@ -22,3 +22,13 @@ impl std::fmt::Display for HealthCheckResult { } } } + +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub enum HealthCheckString { + Passing, + Disabled, + Starting, + Warning, + Failure, +} diff --git a/sdk/lib/health/HealthCheck.ts b/sdk/lib/health/HealthCheck.ts index 8f0bcf81e..1cbc5ebf2 100644 --- a/sdk/lib/health/HealthCheck.ts +++ b/sdk/lib/health/HealthCheck.ts @@ -47,10 +47,10 @@ export function healthCheck(o: { } catch (e) { await o.effects.setHealth({ name: o.name, - status: "failing", + status: "failure", message: asMessage(e), }) - currentValue.lastResult = "failing" + currentValue.lastResult = "failure" } } }) diff --git a/sdk/lib/health/checkFns/checkPortListening.ts b/sdk/lib/health/checkFns/checkPortListening.ts index 07144071b..a82b75fd4 100644 --- a/sdk/lib/health/checkFns/checkPortListening.ts +++ b/sdk/lib/health/checkFns/checkPortListening.ts @@ -48,7 +48,7 @@ export async function checkPortListening( return { status: "passing", message: options.successMessage } } return { - status: "failing", + status: "failure", message: options.errorMessage, } }), @@ -56,7 +56,7 @@ export async function checkPortListening( setTimeout( () => resolve({ - status: "failing", + status: "failure", message: options.timeoutMessage || `Timeout trying to check port ${port}`, }), diff --git a/sdk/lib/health/checkFns/checkWebUrl.ts b/sdk/lib/health/checkFns/checkWebUrl.ts index 81da2b425..d18509ee3 100644 --- a/sdk/lib/health/checkFns/checkWebUrl.ts +++ b/sdk/lib/health/checkFns/checkWebUrl.ts @@ -19,14 +19,17 @@ export const checkWebUrl = async ( } = {}, ): Promise => { return Promise.race([fetch(url), timeoutPromise(timeout)]) - .then((x) => ({ - status: "passing" as const, - message: successMessage, - })) + .then( + (x) => + ({ + status: "passing", + message: successMessage, + }) as const, + ) .catch((e) => { console.warn(`Error while fetching URL: ${url}`) console.error(JSON.stringify(e)) console.error(e.toString()) - return { status: "failing" as const, message: errorMessage } + return { status: "failure" as const, message: errorMessage } }) } diff --git a/sdk/lib/health/checkFns/runHealthScript.ts b/sdk/lib/health/checkFns/runHealthScript.ts index 4bc4556e9..659c787f8 100644 --- a/sdk/lib/health/checkFns/runHealthScript.ts +++ b/sdk/lib/health/checkFns/runHealthScript.ts @@ -29,7 +29,7 @@ export const runHealthScript = async ( console.warn(errorMessage) console.warn(JSON.stringify(e)) console.warn(e.toString()) - throw { status: "failing", message: errorMessage } as CheckResult + throw { status: "failure", message: errorMessage } as CheckResult }) return { status: "passing", diff --git a/sdk/lib/mainFn/Daemons.ts b/sdk/lib/mainFn/Daemons.ts index e9986ad3f..c240427bc 100644 --- a/sdk/lib/mainFn/Daemons.ts +++ b/sdk/lib/mainFn/Daemons.ts @@ -121,7 +121,7 @@ export class Daemons { const response = await Promise.resolve(daemon.ready.fn()).catch( (err) => ({ - status: "failing", + status: "failure", message: "message" in err ? err.message : String(err), }) as CheckResult, ) diff --git a/sdk/lib/types.ts b/sdk/lib/types.ts index cb1946818..a53b3d273 100644 --- a/sdk/lib/types.ts +++ b/sdk/lib/types.ts @@ -133,7 +133,12 @@ export type Daemon = { [DaemonProof]: never } -export type HealthStatus = "passing" | "warning" | "failing" | "disabled" +export type HealthStatus = + | `passing` + | `disabled` + | `starting` + | `warning` + | `failure` export type SmtpValue = { server: string