Scaffold shre-embed: embedding + semantic search with three-valued health
Express (ESM, no build step) service wrapping Ollama embeddings and Qdrant: - POST /v1/embed, /v1/index, /v1/search - GET /health reports each dependency as ok | absent | unobservable with the exact measurement_surface URL and observed_at; overall ok only when all deps are ok, 503 degraded otherwise - upstream failures on /v1/* return 502 marked unobservable — never an empty result set or indexed:0 - defaults PORT=5499, QDRANT_URL=127.0.0.1:6333, OLLAMA_URL=127.0.0.1:11436 (11436 native Ollama; 11434 is the broken Colima forward on this Mac) - node:test unit tests with injected fetch; run with zero live dependencies - README documents endpoints and a reference launchd plist (not installed) Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
// Three-valued observability primitives.
|
||||
//
|
||||
// Every probe answer is one of THREE states, never two:
|
||||
// "ok" — the probe saw the thing and it is present/working
|
||||
// "absent" — the probe SAW the surface and the thing is genuinely missing
|
||||
// "unobservable" — the probe COULD NOT SEE (dependency down, timeout, auth
|
||||
// failure, endpoint missing). Never collapsed into ok/absent.
|
||||
//
|
||||
// Every result carries measurement_surface (exactly what was measured) and
|
||||
// observed_at (ISO timestamp).
|
||||
|
||||
export const OK = "ok";
|
||||
export const ABSENT = "absent";
|
||||
export const UNOBSERVABLE = "unobservable";
|
||||
|
||||
export function probeResult(status, measurementSurface, extra = {}) {
|
||||
return {
|
||||
status,
|
||||
measurement_surface: measurementSurface,
|
||||
observed_at: new Date().toISOString(),
|
||||
...extra,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an HTTP GET probe of `url`. Returns a three-valued probeResult:
|
||||
* - ok when the response status passes `okWhen` (default: 2xx)
|
||||
* - unobservable on network error, timeout, or non-passing HTTP status
|
||||
* (a 401/404/500 from the surface means we could not observe the truth,
|
||||
* not that the dependency is healthy or absent).
|
||||
* `classify(response, bodyText)` may optionally downgrade an HTTP-ok response
|
||||
* to ABSENT (e.g. endpoint reachable but required model not installed).
|
||||
*/
|
||||
export async function httpProbe(url, { fetchImpl = fetch, timeoutMs = 2500, classify } = {}) {
|
||||
const started = Date.now();
|
||||
let res;
|
||||
try {
|
||||
res = await fetchImpl(url, { signal: AbortSignal.timeout(timeoutMs) });
|
||||
} catch (err) {
|
||||
return probeResult(UNOBSERVABLE, url, {
|
||||
reason: `fetch failed: ${err?.cause?.code || err?.name || "error"}: ${err?.message}`,
|
||||
latency_ms: Date.now() - started,
|
||||
});
|
||||
}
|
||||
const latency = Date.now() - started;
|
||||
if (!res.ok) {
|
||||
return probeResult(UNOBSERVABLE, url, {
|
||||
reason: `HTTP ${res.status} from probe surface`,
|
||||
http_status: res.status,
|
||||
latency_ms: latency,
|
||||
});
|
||||
}
|
||||
if (classify) {
|
||||
let bodyText = "";
|
||||
try {
|
||||
bodyText = await res.text();
|
||||
} catch {
|
||||
return probeResult(UNOBSERVABLE, url, {
|
||||
reason: "response body unreadable",
|
||||
latency_ms: latency,
|
||||
});
|
||||
}
|
||||
const classified = classify(res, bodyText);
|
||||
if (classified) return probeResult(classified.status, url, { latency_ms: latency, ...classified.extra });
|
||||
}
|
||||
return probeResult(OK, url, { http_status: res.status, latency_ms: latency });
|
||||
}
|
||||
Reference in New Issue
Block a user