@sylphx/sdk 0.12.1 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/health/index.d.ts +9 -12
- package/dist/health/index.mjs +25 -14
- package/dist/health/index.mjs.map +1 -1
- package/dist/index.d.ts +11 -12
- package/dist/index.mjs +23 -23
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/health/index.d.ts
CHANGED
|
@@ -591,12 +591,10 @@ declare function evaluateEffect(evaluator: () => Promise<HealthScore>): Effect.E
|
|
|
591
591
|
* (Hono / Bun.serve / itty-router / Next.js routes) or, via thin adapters,
|
|
592
592
|
* a Node `(req, res) => void` (Express / Fastify-as-classic-handler).
|
|
593
593
|
*
|
|
594
|
-
* The handler
|
|
595
|
-
*
|
|
596
|
-
*
|
|
597
|
-
*
|
|
598
|
-
* can decide. This separation is documented in the README ("apps don't
|
|
599
|
-
* need to think about probe semantics").
|
|
594
|
+
* The handler returns HTTP 200 for scores at or above the direct-probe
|
|
595
|
+
* liveness floor and HTTP 503 below it. The response body is always the
|
|
596
|
+
* complete HealthSnapshot, so the ADR-111 sidecar can still read the score
|
|
597
|
+
* even when direct kubelet probes need a status-coded failure.
|
|
600
598
|
*/
|
|
601
599
|
|
|
602
600
|
/**
|
|
@@ -791,18 +789,17 @@ type HonoNextLike = () => Promise<void>;
|
|
|
791
789
|
*
|
|
792
790
|
* The returned function carries a `.health` reference (the underlying
|
|
793
791
|
* `SylphxHealth` instance) and a `.dispose()` method for graceful
|
|
794
|
-
* shutdown. Wire
|
|
795
|
-
*
|
|
792
|
+
* shutdown. Wire `.dispose()` into the app entry point's existing
|
|
793
|
+
* graceful-shutdown coordinator.
|
|
796
794
|
*
|
|
797
795
|
* ```ts
|
|
798
796
|
* const health = withHealth.hono()
|
|
799
797
|
* app.use('*', health)
|
|
800
|
-
*
|
|
801
|
-
* // onShutdown(() => health.dispose())
|
|
798
|
+
* registerShutdown(() => health.dispose())
|
|
802
799
|
* ```
|
|
803
800
|
*/
|
|
804
801
|
interface HonoHealthMiddleware {
|
|
805
|
-
(c: HonoContextLike, next: HonoNextLike): Promise<Response |
|
|
802
|
+
(c: HonoContextLike, next: HonoNextLike): Promise<Response | undefined>;
|
|
806
803
|
readonly health: SylphxHealth;
|
|
807
804
|
dispose(): void;
|
|
808
805
|
}
|
|
@@ -838,7 +835,7 @@ interface FastifyInstanceLike {
|
|
|
838
835
|
interface FastifyReplyLike {
|
|
839
836
|
code(code: number): FastifyReplyLike;
|
|
840
837
|
header(name: string, value: string): FastifyReplyLike;
|
|
841
|
-
send(body?: unknown):
|
|
838
|
+
send(body?: unknown): unknown;
|
|
842
839
|
}
|
|
843
840
|
interface FastifyHealthPlugin {
|
|
844
841
|
(instance: FastifyInstanceLike, opts?: unknown): Promise<void>;
|
package/dist/health/index.mjs
CHANGED
|
@@ -18,14 +18,10 @@ async function tryLoadCausalityApi() {
|
|
|
18
18
|
}
|
|
19
19
|
return cachedApi;
|
|
20
20
|
}
|
|
21
|
-
function resolveServiceNameFromEnv(env) {
|
|
22
|
-
if (env.OTEL_SERVICE_NAME) return env.OTEL_SERVICE_NAME;
|
|
23
|
-
if (env.SERVICE_NAME) return env.SERVICE_NAME;
|
|
24
|
-
return "unknown";
|
|
25
|
-
}
|
|
26
21
|
function defaultServiceName() {
|
|
27
22
|
if (typeof process !== "undefined" && process.env) {
|
|
28
|
-
|
|
23
|
+
if (process.env.OTEL_SERVICE_NAME !== void 0) return process.env.OTEL_SERVICE_NAME;
|
|
24
|
+
if (process.env.SERVICE_NAME !== void 0) return process.env.SERVICE_NAME;
|
|
29
25
|
}
|
|
30
26
|
return "unknown";
|
|
31
27
|
}
|
|
@@ -203,12 +199,16 @@ function evaluateEffect(evaluator) {
|
|
|
203
199
|
}
|
|
204
200
|
|
|
205
201
|
// src/health/handler.ts
|
|
202
|
+
var DIRECT_PROBE_LIVENESS_FLOOR = 0.5;
|
|
203
|
+
function statusForScore(score) {
|
|
204
|
+
return Number.isFinite(score) && score >= DIRECT_PROBE_LIVENESS_FLOOR ? 200 : 503;
|
|
205
|
+
}
|
|
206
206
|
function createWebHandler(source) {
|
|
207
207
|
return async (_req) => {
|
|
208
208
|
try {
|
|
209
209
|
const score = await source.evaluate();
|
|
210
210
|
return new Response(JSON.stringify(score), {
|
|
211
|
-
status:
|
|
211
|
+
status: statusForScore(score.score),
|
|
212
212
|
headers: {
|
|
213
213
|
"Content-Type": "application/json",
|
|
214
214
|
// Cache-Control: never cache. Even 1-second cache on a
|
|
@@ -238,7 +238,7 @@ function createNodeHandler(source) {
|
|
|
238
238
|
return async (_req, res) => {
|
|
239
239
|
try {
|
|
240
240
|
const score = await source.evaluate();
|
|
241
|
-
res.statusCode =
|
|
241
|
+
res.statusCode = statusForScore(score.score);
|
|
242
242
|
res.setHeader("Content-Type", "application/json");
|
|
243
243
|
res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
|
|
244
244
|
res.end(JSON.stringify(score));
|
|
@@ -255,6 +255,8 @@ function createNodeHandler(source) {
|
|
|
255
255
|
// src/health/history.ts
|
|
256
256
|
var GENESIS_PREV_HASH = "0".repeat(64);
|
|
257
257
|
var DEFAULT_HISTORY_CAPACITY = 1e3;
|
|
258
|
+
var HASH_TEXT_ENCODER = new TextEncoder();
|
|
259
|
+
var HEX_BYTE = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
|
|
258
260
|
function canonicalizeSignals(signals) {
|
|
259
261
|
const keys = Object.keys(signals).sort();
|
|
260
262
|
const pairs = keys.map((k) => {
|
|
@@ -271,12 +273,12 @@ async function sha256Hex(input) {
|
|
|
271
273
|
if (!subtle || typeof subtle.digest !== "function") {
|
|
272
274
|
return "";
|
|
273
275
|
}
|
|
274
|
-
const buf =
|
|
276
|
+
const buf = HASH_TEXT_ENCODER.encode(input);
|
|
275
277
|
const digest = await subtle.digest("SHA-256", buf);
|
|
276
278
|
const bytes = new Uint8Array(digest);
|
|
277
279
|
let out = "";
|
|
278
280
|
for (let i = 0; i < bytes.length; i++) {
|
|
279
|
-
out +=
|
|
281
|
+
out += HEX_BYTE[bytes[i]];
|
|
280
282
|
}
|
|
281
283
|
return out;
|
|
282
284
|
}
|
|
@@ -379,7 +381,14 @@ var HistoryRecorderImpl = class {
|
|
|
379
381
|
this.inFlight = job.catch(() => void 0);
|
|
380
382
|
return await job;
|
|
381
383
|
}
|
|
384
|
+
async drainPendingRecords() {
|
|
385
|
+
try {
|
|
386
|
+
await this.inFlight;
|
|
387
|
+
} catch {
|
|
388
|
+
}
|
|
389
|
+
}
|
|
382
390
|
async range(query) {
|
|
391
|
+
await this.drainPendingRecords();
|
|
383
392
|
try {
|
|
384
393
|
return await this.store.range(query);
|
|
385
394
|
} catch {
|
|
@@ -387,6 +396,7 @@ var HistoryRecorderImpl = class {
|
|
|
387
396
|
}
|
|
388
397
|
}
|
|
389
398
|
async latest() {
|
|
399
|
+
await this.drainPendingRecords();
|
|
390
400
|
try {
|
|
391
401
|
return await this.store.latest();
|
|
392
402
|
} catch {
|
|
@@ -766,9 +776,9 @@ function getEnvSocketPath() {
|
|
|
766
776
|
const value = proc?.env?.SYLPHX_HEALTH_APP_SOCKET;
|
|
767
777
|
return value && value.trim().length > 0 ? value.trim() : void 0;
|
|
768
778
|
}
|
|
769
|
-
function
|
|
770
|
-
if (
|
|
771
|
-
if (envPath) return envPath;
|
|
779
|
+
function resolveUnixSocketPath(inputPath, envPath) {
|
|
780
|
+
if (inputPath !== void 0) return inputPath;
|
|
781
|
+
if (envPath !== void 0) return envPath;
|
|
772
782
|
return DEFAULT_SOCKET_PATH;
|
|
773
783
|
}
|
|
774
784
|
function resolveUnixSocketOption(input) {
|
|
@@ -781,7 +791,7 @@ function resolveUnixSocketOption(input) {
|
|
|
781
791
|
return { path: envPath ?? DEFAULT_SOCKET_PATH, required: false };
|
|
782
792
|
}
|
|
783
793
|
return {
|
|
784
|
-
path:
|
|
794
|
+
path: resolveUnixSocketPath(input.path, envPath),
|
|
785
795
|
required: input.required ?? false,
|
|
786
796
|
...input.unlinkOnShutdown !== void 0 ? { unlinkOnShutdown: input.unlinkOnShutdown } : {}
|
|
787
797
|
};
|
|
@@ -816,6 +826,7 @@ function honoHelper(opts = {}) {
|
|
|
816
826
|
const middleware = (async (c, next) => {
|
|
817
827
|
if (c.req.path === path) return respond();
|
|
818
828
|
await health.runWithCause(() => next());
|
|
829
|
+
return void 0;
|
|
819
830
|
});
|
|
820
831
|
Object.defineProperty(middleware, "health", { value: health, enumerable: true });
|
|
821
832
|
Object.defineProperty(middleware, "dispose", {
|