mirror of
https://github.com/Start9Labs/start-sdk.git
synced 2026-04-04 22:39:47 +00:00
feat: Worked with matt to create all the things
This commit is contained in:
75
lib/health/healthRunner.ts
Normal file
75
lib/health/healthRunner.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { Types } from "..";
|
||||
import { object, string } from "ts-matches";
|
||||
|
||||
export type HealthCheck = (
|
||||
effects: Types.Effects,
|
||||
dateMs: number
|
||||
) => Promise<HealthResult>;
|
||||
export type HealthResult =
|
||||
| { success: string }
|
||||
| { failure: string }
|
||||
| { disabled: null }
|
||||
| { starting: null }
|
||||
| { loading: string };
|
||||
const hasMessage = object({ message: string }).test;
|
||||
function safelyStringify(e: unknown) {
|
||||
if (hasMessage(e)) return e.message;
|
||||
if (string.test(e)) return e;
|
||||
try {
|
||||
return JSON.stringify(e);
|
||||
} catch (e) {
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
async function timeoutHealth(
|
||||
effects: Types.Effects,
|
||||
timeMs: number
|
||||
): Promise<HealthResult> {
|
||||
await effects.sleep(timeMs);
|
||||
return { failure: "Timed out " };
|
||||
}
|
||||
|
||||
export default function healthRunner(
|
||||
name: string,
|
||||
fn: HealthCheck,
|
||||
{ defaultIntervalS = 60 } = {}
|
||||
) {
|
||||
return {
|
||||
create(effects: Types.Effects, defaultIntervalCreatedS = defaultIntervalS) {
|
||||
let running: any;
|
||||
function startFn(intervalS: number, timeoutS: number, delayS: number) {
|
||||
clearInterval(running);
|
||||
setTimeout(() => {
|
||||
running = setInterval(async () => {
|
||||
const result = await Promise.race([
|
||||
timeoutHealth(effects, timeoutS * 1000),
|
||||
fn(effects, 123),
|
||||
]).catch((e) => {
|
||||
return { failure: safelyStringify(e) };
|
||||
});
|
||||
(effects as any).setHealthStatus({
|
||||
name,
|
||||
result,
|
||||
});
|
||||
}, intervalS * 1000);
|
||||
}, delayS * 1000);
|
||||
}
|
||||
|
||||
const self = {
|
||||
stop() {
|
||||
clearInterval(running);
|
||||
return self;
|
||||
},
|
||||
start({
|
||||
intervalS = defaultIntervalCreatedS,
|
||||
timeoutS = 10,
|
||||
delayS = 0,
|
||||
} = {}) {
|
||||
startFn(intervalS, timeoutS, delayS);
|
||||
return self;
|
||||
},
|
||||
};
|
||||
return self;
|
||||
},
|
||||
};
|
||||
}
|
||||
2
lib/health/index.ts
Normal file
2
lib/health/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./util";
|
||||
export { default as healthRunner } from "./healthRunner";
|
||||
54
lib/health/util.ts
Normal file
54
lib/health/util.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { Effects, ResultType } from "../types";
|
||||
import { error, errorCode, isKnownError, ok } from "../util";
|
||||
export const checkWebUrl: (
|
||||
url: string
|
||||
) => (
|
||||
effects: Effects,
|
||||
duration: number
|
||||
) => Promise<ResultType<null | void>> = (url) => {
|
||||
return async (effects, duration) => {
|
||||
let errorValue;
|
||||
if (
|
||||
// deno-lint-ignore no-cond-assign
|
||||
(errorValue = guardDurationAboveMinimum({ duration, minimumTime: 5000 }))
|
||||
) {
|
||||
return errorValue;
|
||||
}
|
||||
|
||||
return await effects
|
||||
.fetch(url)
|
||||
.then((_) => ok)
|
||||
.catch((e) => {
|
||||
effects.warn(`Error while fetching URL: ${url}`);
|
||||
effects.error(JSON.stringify(e));
|
||||
effects.error(e.toString());
|
||||
return error(`Error while fetching URL: ${url}`);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const runHealthScript =
|
||||
({ command, args }: { command: string; args: string[] }) =>
|
||||
async (
|
||||
effects: Effects,
|
||||
_duration: number
|
||||
): Promise<ResultType<null | void>> => {
|
||||
const res = await effects.runCommand({ command, args });
|
||||
if ("result" in res) {
|
||||
return { result: null };
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
// Ensure the starting duration is pass a minimum
|
||||
export const guardDurationAboveMinimum = (input: {
|
||||
duration: number;
|
||||
minimumTime: number;
|
||||
}) => (input.duration <= input.minimumTime ? errorCode(60, "Starting") : null);
|
||||
|
||||
export const catchError = (effects: Effects) => (e: unknown) => {
|
||||
if (isKnownError(e)) return e;
|
||||
effects.error(`Health check failed: ${e}`);
|
||||
return error("Error while running health check");
|
||||
};
|
||||
Reference in New Issue
Block a user