@vibes.diy/api-svc 12.1.1 → 12.1.3
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/create-handler.d.ts +2 -0
- package/create-handler.js +1 -0
- package/create-handler.js.map +1 -1
- package/evento-handler-manifest.js +5 -0
- package/evento-handler-manifest.js.map +1 -1
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/index.js.map +1 -1
- package/intern/attempt-backend-fetch.d.ts +4 -0
- package/intern/attempt-backend-fetch.js +12 -0
- package/intern/attempt-backend-fetch.js.map +1 -1
- package/intern/attempt-backend-onchange.d.ts +4 -0
- package/intern/attempt-backend-onchange.js +12 -0
- package/intern/attempt-backend-onchange.js.map +1 -1
- package/intern/attempt-backend-scheduled.d.ts +4 -0
- package/intern/attempt-backend-scheduled.js +12 -0
- package/intern/attempt-backend-scheduled.js.map +1 -1
- package/intern/backend-do-addr.d.ts +6 -0
- package/intern/backend-do-addr.js +10 -1
- package/intern/backend-do-addr.js.map +1 -1
- package/intern/backend-do-control-plane.d.ts +34 -0
- package/intern/backend-do-control-plane.js +68 -0
- package/intern/backend-do-control-plane.js.map +1 -0
- package/intern/backend-log-callback.d.ts +20 -0
- package/intern/backend-log-callback.js +47 -0
- package/intern/backend-log-callback.js.map +1 -0
- package/intern/backend-log-op.d.ts +1 -0
- package/intern/backend-log-op.js +2 -0
- package/intern/backend-log-op.js.map +1 -0
- package/intern/backend-log-rate.d.ts +12 -0
- package/intern/backend-log-rate.js +25 -0
- package/intern/backend-log-rate.js.map +1 -0
- package/intern/backend-tick-liveness.d.ts +20 -0
- package/intern/backend-tick-liveness.js +26 -0
- package/intern/backend-tick-liveness.js.map +1 -0
- package/intern/client-log-ingest.d.ts +35 -0
- package/intern/client-log-ingest.js +119 -0
- package/intern/client-log-ingest.js.map +1 -0
- package/intern/load-selected-backend.d.ts +1 -0
- package/intern/load-selected-backend.js +1 -1
- package/intern/load-selected-backend.js.map +1 -1
- package/intern/notify-tick-silent.d.ts +10 -0
- package/intern/notify-tick-silent.js +31 -0
- package/intern/notify-tick-silent.js.map +1 -0
- package/intern/prune-vibe-logs.d.ts +13 -0
- package/intern/prune-vibe-logs.js +26 -0
- package/intern/prune-vibe-logs.js.map +1 -0
- package/intern/swr-html-cache-orchestrator.d.ts +2 -2
- package/intern/swr-html-cache-orchestrator.js +23 -10
- package/intern/swr-html-cache-orchestrator.js.map +1 -1
- package/intern/swr-html-cache.d.ts +3 -1
- package/intern/swr-html-cache.js +4 -3
- package/intern/swr-html-cache.js.map +1 -1
- package/package.json +11 -11
- package/public/app-logs.d.ts +4 -0
- package/public/app-logs.js +109 -0
- package/public/app-logs.js.map +1 -0
- package/public/app-tick.d.ts +4 -0
- package/public/app-tick.js +143 -0
- package/public/app-tick.js.map +1 -0
- package/public/root-html-live-inputs.d.ts +2 -1
- package/public/root-html-live-inputs.js +5 -2
- package/public/root-html-live-inputs.js.map +1 -1
- package/public/serv-entry-point.js +4 -1
- package/public/serv-entry-point.js.map +1 -1
- package/types.d.ts +2 -0
- package/types.js.map +1 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { exception2Result } from "@adviser/cement";
|
|
2
|
+
import { mintLogEventId, newLogIdLatch, normalizeLogLevel, truncateLogBody, } from "@vibes.diy/api-types";
|
|
3
|
+
import { BackendLogRateWindow } from "./backend-log-rate.js";
|
|
4
|
+
export function makeBackendLogCallback(vctx, base) {
|
|
5
|
+
const rate = base.rate ?? new BackendLogRateWindow();
|
|
6
|
+
const idLatch = base.idLatch ?? newLogIdLatch();
|
|
7
|
+
const buffered = [];
|
|
8
|
+
const log = async (op) => {
|
|
9
|
+
const body = typeof op?.body === "string" ? truncateLogBody(op.body) : "";
|
|
10
|
+
if (body.length === 0)
|
|
11
|
+
return { ok: true };
|
|
12
|
+
const now = Date.now();
|
|
13
|
+
if (!rate.admit(now))
|
|
14
|
+
return { ok: true };
|
|
15
|
+
buffered.push({
|
|
16
|
+
id: mintLogEventId(idLatch, now, vctx.sthis.nextId().str),
|
|
17
|
+
ownerHandle: base.ownerHandle,
|
|
18
|
+
appSlug: base.appSlug,
|
|
19
|
+
lane: "backend",
|
|
20
|
+
level: normalizeLogLevel(op?.level),
|
|
21
|
+
ts: new Date(now).toISOString(),
|
|
22
|
+
fsId: base.fsId,
|
|
23
|
+
trigger: base.trigger,
|
|
24
|
+
sessionId: null,
|
|
25
|
+
deviceHash: null,
|
|
26
|
+
viewerHandle: base.viewerHandle ?? null,
|
|
27
|
+
body,
|
|
28
|
+
country: null,
|
|
29
|
+
});
|
|
30
|
+
return { ok: true };
|
|
31
|
+
};
|
|
32
|
+
const flush = async () => {
|
|
33
|
+
if (buffered.length === 0)
|
|
34
|
+
return;
|
|
35
|
+
const rows = buffered.splice(0, buffered.length);
|
|
36
|
+
await exception2Result(() => vctx.sql.db.insert(vctx.sql.tables.vibeLogEvents).values(rows));
|
|
37
|
+
};
|
|
38
|
+
return { log, flush };
|
|
39
|
+
}
|
|
40
|
+
export async function flushBackendLog(vctx, lane) {
|
|
41
|
+
if (vctx.waitUntil) {
|
|
42
|
+
vctx.waitUntil(lane.flush());
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
await lane.flush();
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=backend-log-callback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-log-callback.js","sourceRoot":"","sources":["../../jsr/intern/backend-log-callback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EACL,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,eAAe,GAGhB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAsE7D,MAAM,UAAU,sBAAsB,CACpC,IAAoB,EACpB,IAA4B;IAE5B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,oBAAoB,EAAE,CAAC;IACrD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,aAAa,EAAE,CAAC;IAChD,MAAM,QAAQ,GAAuB,EAAE,CAAC;IAExC,MAAM,GAAG,GAAuB,KAAK,EAAE,EAAgB,EAA6B,EAAE;QACpF,MAAM,IAAI,GAAG,OAAO,EAAE,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAE1E,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QAC1C,QAAQ,CAAC,IAAI,CAAC;YACZ,EAAE,EAAE,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC;YACzD,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,iBAAiB,CAAC,EAAE,EAAE,KAAK,CAAC;YACnC,EAAE,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE;YAC/B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;YAGrB,SAAS,EAAE,IAAI;YACf,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI;YACvC,IAAI;YACJ,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,KAAK,IAAmB,EAAE;QACtC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QAIjD,MAAM,gBAAgB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/F,CAAC,CAAC;IAEF,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AACxB,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAoB,EAAE,IAA6C;IACvG,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7B,OAAO;IACT,CAAC;IACD,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BACKEND_LOG_OP_URL, handleBackendLogOp } from "@vibes.diy/vibe-runtime/backend-executor.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-log-op.js","sourceRoot":"","sources":["../../jsr/intern/backend-log-op.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface LogRateLimits {
|
|
2
|
+
readonly burstLimit: number;
|
|
3
|
+
readonly burstWindowMs: number;
|
|
4
|
+
readonly sustainedLimit: number;
|
|
5
|
+
readonly sustainedWindowMs: number;
|
|
6
|
+
}
|
|
7
|
+
export declare class BackendLogRateWindow {
|
|
8
|
+
private stamps;
|
|
9
|
+
private readonly limits;
|
|
10
|
+
constructor(limits?: LogRateLimits);
|
|
11
|
+
admit(now: number): boolean;
|
|
12
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { LOG_BACKEND_BURST_LIMIT, LOG_BACKEND_BURST_WINDOW_MS, LOG_BACKEND_SUSTAINED_LIMIT, LOG_BACKEND_SUSTAINED_WINDOW_MS, } from "@vibes.diy/api-types";
|
|
2
|
+
const BACKEND_LOG_RATE_LIMITS = {
|
|
3
|
+
burstLimit: LOG_BACKEND_BURST_LIMIT,
|
|
4
|
+
burstWindowMs: LOG_BACKEND_BURST_WINDOW_MS,
|
|
5
|
+
sustainedLimit: LOG_BACKEND_SUSTAINED_LIMIT,
|
|
6
|
+
sustainedWindowMs: LOG_BACKEND_SUSTAINED_WINDOW_MS,
|
|
7
|
+
};
|
|
8
|
+
export class BackendLogRateWindow {
|
|
9
|
+
stamps = [];
|
|
10
|
+
limits;
|
|
11
|
+
constructor(limits = BACKEND_LOG_RATE_LIMITS) {
|
|
12
|
+
this.limits = limits;
|
|
13
|
+
}
|
|
14
|
+
admit(now) {
|
|
15
|
+
this.stamps = this.stamps.filter((s) => now - s < this.limits.sustainedWindowMs);
|
|
16
|
+
const inBurst = this.stamps.filter((s) => now - s < this.limits.burstWindowMs).length;
|
|
17
|
+
if (inBurst >= this.limits.burstLimit)
|
|
18
|
+
return false;
|
|
19
|
+
if (this.stamps.length >= this.limits.sustainedLimit)
|
|
20
|
+
return false;
|
|
21
|
+
this.stamps.push(now);
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=backend-log-rate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-log-rate.js","sourceRoot":"","sources":["../../jsr/intern/backend-log-rate.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,2BAA2B,EAC3B,2BAA2B,EAC3B,+BAA+B,GAChC,MAAM,sBAAsB,CAAC;AA+B9B,MAAM,uBAAuB,GAAkB;IAC7C,UAAU,EAAE,uBAAuB;IACnC,aAAa,EAAE,2BAA2B;IAC1C,cAAc,EAAE,2BAA2B;IAC3C,iBAAiB,EAAE,+BAA+B;CACnD,CAAC;AAEF,MAAM,OAAO,oBAAoB;IACvB,MAAM,GAAa,EAAE,CAAC;IACb,MAAM,CAAgB;IAGvC,YAAY,MAAM,GAAkB,uBAAuB;QACzD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAGD,KAAK,CAAC,GAAW;QACf,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACjF,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC;QACtF,IAAI,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,OAAO,KAAK,CAAC;QACpD,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc;YAAE,OAAO,KAAK,CAAC;QACnE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const OVERDUE_GRACE_MULTIPLE = 3;
|
|
2
|
+
export declare const MIN_GRACE_MS: number;
|
|
3
|
+
export type TickLivenessState = "unscheduled" | "running" | "healthy" | "overdue" | "dead";
|
|
4
|
+
export interface TickLivenessInput {
|
|
5
|
+
readonly intervalMs: number | null;
|
|
6
|
+
readonly armedAt?: string;
|
|
7
|
+
readonly lastAttemptAt?: string;
|
|
8
|
+
readonly lastRunAt?: string;
|
|
9
|
+
readonly nextAlarmAt: number | null;
|
|
10
|
+
readonly ticking: boolean;
|
|
11
|
+
readonly now: number;
|
|
12
|
+
}
|
|
13
|
+
export interface TickLivenessVerdict {
|
|
14
|
+
readonly state: TickLivenessState;
|
|
15
|
+
readonly graceMs: number;
|
|
16
|
+
readonly silenceMs: number;
|
|
17
|
+
readonly overdueMs: number;
|
|
18
|
+
readonly nextExpectedAt: string | null;
|
|
19
|
+
}
|
|
20
|
+
export declare function tickLiveness(input: TickLivenessInput): TickLivenessVerdict;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const OVERDUE_GRACE_MULTIPLE = 3;
|
|
2
|
+
export const MIN_GRACE_MS = 5 * 60_000;
|
|
3
|
+
function instant(iso) {
|
|
4
|
+
if (iso === undefined)
|
|
5
|
+
return undefined;
|
|
6
|
+
const ms = Date.parse(iso);
|
|
7
|
+
return Number.isFinite(ms) ? ms : undefined;
|
|
8
|
+
}
|
|
9
|
+
export function tickLiveness(input) {
|
|
10
|
+
const nextExpectedAt = input.nextAlarmAt === null ? null : new Date(input.nextAlarmAt).toISOString();
|
|
11
|
+
if (input.intervalMs === null) {
|
|
12
|
+
return { state: "unscheduled", graceMs: 0, silenceMs: 0, overdueMs: 0, nextExpectedAt: null };
|
|
13
|
+
}
|
|
14
|
+
const graceMs = Math.max(MIN_GRACE_MS, input.intervalMs * OVERDUE_GRACE_MULTIPLE);
|
|
15
|
+
const reference = instant(input.lastAttemptAt) ?? instant(input.lastRunAt) ?? instant(input.armedAt);
|
|
16
|
+
const silenceMs = reference === undefined ? 0 : Math.max(0, input.now - reference);
|
|
17
|
+
const overdueMs = Math.max(0, silenceMs - graceMs);
|
|
18
|
+
if (input.ticking) {
|
|
19
|
+
return { state: "running", graceMs, silenceMs, overdueMs, nextExpectedAt };
|
|
20
|
+
}
|
|
21
|
+
if (input.nextAlarmAt === null) {
|
|
22
|
+
return { state: "dead", graceMs, silenceMs, overdueMs, nextExpectedAt: null };
|
|
23
|
+
}
|
|
24
|
+
return { state: overdueMs > 0 ? "overdue" : "healthy", graceMs, silenceMs, overdueMs, nextExpectedAt };
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=backend-tick-liveness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-tick-liveness.js","sourceRoot":"","sources":["../../jsr/intern/backend-tick-liveness.ts"],"names":[],"mappings":"AAsBA,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAExC,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAG,MAAM,CAAC;AAmDvC,SAAS,OAAO,CAAC,GAAuB;IACtC,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9C,CAAC;AA0BD,MAAM,UAAU,YAAY,CAAC,KAAwB;IACnD,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;IACrG,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAC9B,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;IAChG,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,UAAU,GAAG,sBAAsB,CAAC,CAAC;IAGlF,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAErG,MAAM,SAAS,GAAG,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC;IACnF,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC;IACnD,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAGlB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;IAC7E,CAAC;IACD,IAAI,KAAK,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;QAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;IAChF,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;AACzG,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type LogIdLatch } from "@vibes.diy/api-types";
|
|
2
|
+
import { VibesApiSQLCtx } from "../types.js";
|
|
3
|
+
export declare function exceedsClientLogByteCap(body: string): boolean;
|
|
4
|
+
export type ClientLogVisibility = "visible" | "hidden";
|
|
5
|
+
export interface ClientLogEvent {
|
|
6
|
+
readonly level: string;
|
|
7
|
+
readonly body: string;
|
|
8
|
+
readonly visibility: ClientLogVisibility | null;
|
|
9
|
+
readonly hiddenMs: number | null;
|
|
10
|
+
}
|
|
11
|
+
export interface ClientLogBatch {
|
|
12
|
+
readonly sessionId: string | null;
|
|
13
|
+
readonly deviceHash: string | null;
|
|
14
|
+
readonly fsId: string;
|
|
15
|
+
readonly viewerHandle: string | null;
|
|
16
|
+
readonly events: readonly ClientLogEvent[];
|
|
17
|
+
}
|
|
18
|
+
export declare function parseClientLogBatch(raw: unknown): ClientLogBatch | undefined;
|
|
19
|
+
export declare class ClientLogRateWindows {
|
|
20
|
+
private readonly windows;
|
|
21
|
+
admit(deviceHash: string, now: number): boolean;
|
|
22
|
+
get size(): number;
|
|
23
|
+
}
|
|
24
|
+
export interface ClientLogIngestBase {
|
|
25
|
+
readonly ownerHandle: string;
|
|
26
|
+
readonly appSlug: string;
|
|
27
|
+
readonly country: string | null;
|
|
28
|
+
readonly rate?: ClientLogRateWindows;
|
|
29
|
+
readonly idLatch?: LogIdLatch;
|
|
30
|
+
}
|
|
31
|
+
export interface ClientLogIngestResult {
|
|
32
|
+
readonly admitted: number;
|
|
33
|
+
readonly dropped: number;
|
|
34
|
+
}
|
|
35
|
+
export declare function ingestClientLogBatch(vctx: VibesApiSQLCtx, base: ClientLogIngestBase, batch: ClientLogBatch): Promise<ClientLogIngestResult>;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { exception2Result } from "@adviser/cement";
|
|
2
|
+
import { LOG_CLIENT_BATCH_MAX_EVENTS, LOG_CLIENT_BURST_LIMIT, LOG_CLIENT_BURST_WINDOW_MS, LOG_CLIENT_DEVICE_WINDOWS_MAX, LOG_CLIENT_REQUEST_MAX_BYTES, LOG_CLIENT_SUSTAINED_LIMIT, LOG_CLIENT_SUSTAINED_WINDOW_MS, LOG_CLIENT_TRIGGER, mintLogEventId, newLogIdLatch, normalizeLogLevel, truncateLogBody, } from "@vibes.diy/api-types";
|
|
3
|
+
import { BackendLogRateWindow } from "./backend-log-rate.js";
|
|
4
|
+
const SESSION_ID_MAX = 64;
|
|
5
|
+
const DEVICE_HASH_MAX = 64;
|
|
6
|
+
const FS_ID_MAX = 128;
|
|
7
|
+
const VIEWER_HANDLE_MAX = 64;
|
|
8
|
+
const HIDDEN_MS_MAX = 7 * 24 * 60 * 60 * 1000;
|
|
9
|
+
const CLIENT_LOG_RATE_LIMITS = {
|
|
10
|
+
burstLimit: LOG_CLIENT_BURST_LIMIT,
|
|
11
|
+
burstWindowMs: LOG_CLIENT_BURST_WINDOW_MS,
|
|
12
|
+
sustainedLimit: LOG_CLIENT_SUSTAINED_LIMIT,
|
|
13
|
+
sustainedWindowMs: LOG_CLIENT_SUSTAINED_WINDOW_MS,
|
|
14
|
+
};
|
|
15
|
+
export function exceedsClientLogByteCap(body) {
|
|
16
|
+
return new TextEncoder().encode(body).length > LOG_CLIENT_REQUEST_MAX_BYTES;
|
|
17
|
+
}
|
|
18
|
+
function boundedString(v, max) {
|
|
19
|
+
if (typeof v !== "string")
|
|
20
|
+
return null;
|
|
21
|
+
const s = v.slice(0, max);
|
|
22
|
+
return s.length === 0 ? null : s;
|
|
23
|
+
}
|
|
24
|
+
function boundedHiddenMs(v) {
|
|
25
|
+
if (typeof v !== "number" || !Number.isFinite(v) || v < 0)
|
|
26
|
+
return null;
|
|
27
|
+
return Math.min(Math.floor(v), HIDDEN_MS_MAX);
|
|
28
|
+
}
|
|
29
|
+
function visibilityOf(v) {
|
|
30
|
+
return v === "visible" || v === "hidden" ? v : null;
|
|
31
|
+
}
|
|
32
|
+
export function parseClientLogBatch(raw) {
|
|
33
|
+
if (typeof raw !== "object" || raw === null)
|
|
34
|
+
return undefined;
|
|
35
|
+
const b = raw;
|
|
36
|
+
const rawEvents = Array.isArray(b.events) ? b.events : [];
|
|
37
|
+
const events = [];
|
|
38
|
+
for (const e of rawEvents.slice(0, LOG_CLIENT_BATCH_MAX_EVENTS)) {
|
|
39
|
+
if (typeof e !== "object" || e === null)
|
|
40
|
+
continue;
|
|
41
|
+
const ev = e;
|
|
42
|
+
const body = typeof ev.body === "string" ? truncateLogBody(ev.body) : "";
|
|
43
|
+
if (body.length === 0)
|
|
44
|
+
continue;
|
|
45
|
+
events.push({
|
|
46
|
+
level: normalizeLogLevel(ev.level),
|
|
47
|
+
body,
|
|
48
|
+
visibility: visibilityOf(ev.visibility),
|
|
49
|
+
hiddenMs: boundedHiddenMs(ev.hiddenMs),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
if (events.length === 0)
|
|
53
|
+
return undefined;
|
|
54
|
+
return {
|
|
55
|
+
sessionId: boundedString(b.sessionId, SESSION_ID_MAX),
|
|
56
|
+
deviceHash: boundedString(b.deviceHash, DEVICE_HASH_MAX),
|
|
57
|
+
fsId: boundedString(b.fsId, FS_ID_MAX) ?? "unknown",
|
|
58
|
+
viewerHandle: boundedString(b.viewerHandle, VIEWER_HANDLE_MAX),
|
|
59
|
+
events,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export class ClientLogRateWindows {
|
|
63
|
+
windows = new Map();
|
|
64
|
+
admit(deviceHash, now) {
|
|
65
|
+
const existing = this.windows.get(deviceHash);
|
|
66
|
+
if (existing) {
|
|
67
|
+
this.windows.delete(deviceHash);
|
|
68
|
+
this.windows.set(deviceHash, existing);
|
|
69
|
+
return existing.admit(now);
|
|
70
|
+
}
|
|
71
|
+
if (this.windows.size >= LOG_CLIENT_DEVICE_WINDOWS_MAX) {
|
|
72
|
+
const oldest = this.windows.keys().next();
|
|
73
|
+
if (!oldest.done)
|
|
74
|
+
this.windows.delete(oldest.value);
|
|
75
|
+
}
|
|
76
|
+
const fresh = new BackendLogRateWindow(CLIENT_LOG_RATE_LIMITS);
|
|
77
|
+
this.windows.set(deviceHash, fresh);
|
|
78
|
+
return fresh.admit(now);
|
|
79
|
+
}
|
|
80
|
+
get size() {
|
|
81
|
+
return this.windows.size;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export async function ingestClientLogBatch(vctx, base, batch) {
|
|
85
|
+
const rate = base.rate ?? new ClientLogRateWindows();
|
|
86
|
+
const idLatch = base.idLatch ?? newLogIdLatch();
|
|
87
|
+
const key = batch.deviceHash ?? "unkeyed";
|
|
88
|
+
const now = Date.now();
|
|
89
|
+
const rows = [];
|
|
90
|
+
let dropped = 0;
|
|
91
|
+
for (const ev of batch.events) {
|
|
92
|
+
if (!rate.admit(key, now)) {
|
|
93
|
+
dropped++;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
rows.push({
|
|
97
|
+
id: mintLogEventId(idLatch, now, vctx.sthis.nextId().str),
|
|
98
|
+
ownerHandle: base.ownerHandle,
|
|
99
|
+
appSlug: base.appSlug,
|
|
100
|
+
lane: "client",
|
|
101
|
+
level: ev.level,
|
|
102
|
+
ts: new Date(now).toISOString(),
|
|
103
|
+
fsId: batch.fsId,
|
|
104
|
+
trigger: LOG_CLIENT_TRIGGER,
|
|
105
|
+
sessionId: batch.sessionId,
|
|
106
|
+
deviceHash: batch.deviceHash,
|
|
107
|
+
viewerHandle: batch.viewerHandle,
|
|
108
|
+
body: ev.body,
|
|
109
|
+
country: base.country,
|
|
110
|
+
visibility: ev.visibility,
|
|
111
|
+
hiddenMs: ev.hiddenMs,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
if (rows.length === 0)
|
|
115
|
+
return { admitted: 0, dropped };
|
|
116
|
+
await exception2Result(() => vctx.sql.db.insert(vctx.sql.tables.vibeLogEvents).values(rows));
|
|
117
|
+
return { admitted: rows.length, dropped };
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=client-log-ingest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-log-ingest.js","sourceRoot":"","sources":["../../jsr/intern/client-log-ingest.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,7 +19,7 @@ export async function loadSelectedBackend(vctx, ownerHandle, appSlug) {
|
|
|
19
19
|
const source = rSource.Ok();
|
|
20
20
|
if (source.length === 0)
|
|
21
21
|
return { ok: false, reason: "source_unreadable" };
|
|
22
|
-
return { ok: true, source, parsed: parseBackendConfig(source) };
|
|
22
|
+
return { ok: true, source, parsed: parseBackendConfig(source), fsId: row.fsId };
|
|
23
23
|
}
|
|
24
24
|
export async function resolveBackendSchedule(vctx, ownerHandle, appSlug) {
|
|
25
25
|
const loaded = await loadSelectedBackend(vctx, ownerHandle, appSlug);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-selected-backend.js","sourceRoot":"","sources":["../../jsr/intern/load-selected-backend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAE,kBAAkB,EAAiC,MAAM,iDAAiD,CAAC;AAEpH,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,MAAM,gBAAgB,GAAG,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"load-selected-backend.js","sourceRoot":"","sources":["../../jsr/intern/load-selected-backend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAE,kBAAkB,EAAiC,MAAM,iDAAiD,CAAC;AAEpH,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAiCvC,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAoB,EACpB,WAAmB,EACnB,OAAe;IAEf,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,CAAC,sBAAsB,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAClG,IAAI,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IACtB,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAElE,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAqB,CAAC;IAC9D,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,gBAAgB,CAAC,CAAC;IAC5E,IAAI,WAAW,KAAK,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAE/E,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrF,IAAI,OAAO,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IACvE,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,EAAE,CAAC;IAC5B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAE3E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;AAClF,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,IAAoB,EAAE,WAAmB,EAAE,OAAe;IACrG,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IACrE,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/D,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,IAAI,IAAI,CAAC;AACpD,CAAC;AAGD,KAAK,UAAU,UAAU,CAAC,IAAoB,EAAE,QAAgB;IAC9D,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC,IAAI,QAAQ,QAAQ,EAAE,CAAC,CAAC;IAC7F,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EmitNotificationCtx } from "./emit-notification.js";
|
|
2
|
+
import { TickLivenessState } from "./backend-tick-liveness.js";
|
|
3
|
+
export interface TickSilentNotifyInput {
|
|
4
|
+
readonly ownerHandle: string;
|
|
5
|
+
readonly appSlug: string;
|
|
6
|
+
readonly state: TickLivenessState;
|
|
7
|
+
readonly silenceMs: number;
|
|
8
|
+
readonly now?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function notifyTickSilent(qctx: EmitNotificationCtx, input: TickSilentNotifyInput): Promise<void>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { eq } from "drizzle-orm/sql/expressions";
|
|
2
|
+
import { emitNotification } from "./emit-notification.js";
|
|
3
|
+
import { humanizeDuration } from "@vibes.diy/api-types";
|
|
4
|
+
export async function notifyTickSilent(qctx, input) {
|
|
5
|
+
if (input.state !== "dead" && input.state !== "overdue")
|
|
6
|
+
return;
|
|
7
|
+
const hb = qctx.sql.tables.handleBinding;
|
|
8
|
+
const owner = await qctx.sql.db
|
|
9
|
+
.select({ userId: hb.userId })
|
|
10
|
+
.from(hb)
|
|
11
|
+
.where(eq(hb.handle, input.ownerHandle))
|
|
12
|
+
.limit(1)
|
|
13
|
+
.then((r) => r[0]);
|
|
14
|
+
if (owner === undefined)
|
|
15
|
+
return;
|
|
16
|
+
const app = `${input.ownerHandle}/${input.appSlug}`;
|
|
17
|
+
const since = input.silenceMs > 0 ? ` It last tried about ${humanizeDuration(input.silenceMs)} ago.` : "";
|
|
18
|
+
const body = input.state === "dead"
|
|
19
|
+
? `The scheduled task in ${app} had no timer registered, so it was not going to run again. We restarted it.${since}`
|
|
20
|
+
: `The scheduled task in ${app} has not run for about ${humanizeDuration(input.silenceMs)}.`;
|
|
21
|
+
const day = new Date(input.now ?? Date.now()).toISOString().slice(0, 10);
|
|
22
|
+
await emitNotification(qctx, {
|
|
23
|
+
userId: owner.userId,
|
|
24
|
+
notificationType: "app-message",
|
|
25
|
+
ownerHandle: input.ownerHandle,
|
|
26
|
+
appSlug: input.appSlug,
|
|
27
|
+
body,
|
|
28
|
+
dedupeKey: `tick-silent:${app}:${day}`,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=notify-tick-silent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify-tick-silent.js","sourceRoot":"","sources":["../../jsr/intern/notify-tick-silent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAuB,MAAM,wBAAwB,CAAC;AAE/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAgDxD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAyB,EAAE,KAA4B;IAC5F,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO;IAEhE,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC;IACzC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,EAAE;SAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC;SAC7B,IAAI,CAAC,EAAE,CAAC;SACR,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;SACvC,KAAK,CAAC,CAAC,CAAC;SACR,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrB,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO;IAEhC,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;IAGpD,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,wBAAwB,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1G,MAAM,IAAI,GACR,KAAK,CAAC,KAAK,KAAK,MAAM;QACpB,CAAC,CAAC,yBAAyB,GAAG,+EAA+E,KAAK,EAAE;QACpH,CAAC,CAAC,yBAAyB,GAAG,0BAA0B,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC;IAEjG,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACzE,MAAM,gBAAgB,CAAC,IAAI,EAAE;QAC3B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,gBAAgB,EAAE,aAAa;QAC/B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI;QACJ,SAAS,EAAE,eAAe,GAAG,IAAI,GAAG,EAAE;KACvC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { cfDrizzle, VibesApiTables } from "@vibes.diy/api-sql";
|
|
2
|
+
export interface PruneVibeLogsSql {
|
|
3
|
+
readonly db: ReturnType<typeof cfDrizzle>["db"];
|
|
4
|
+
readonly tables: VibesApiTables;
|
|
5
|
+
}
|
|
6
|
+
export declare const PRUNE_BATCH_SIZE = 5000;
|
|
7
|
+
export declare const PRUNE_MAX_BATCHES = 20;
|
|
8
|
+
export interface PruneVibeLogsResult {
|
|
9
|
+
readonly deleted: number;
|
|
10
|
+
readonly prunedThrough: string;
|
|
11
|
+
readonly capped: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function pruneVibeLogEvents(sql: PruneVibeLogsSql, nowMs: number): Promise<PruneVibeLogsResult>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { and, asc, lt, lte } from "drizzle-orm/sql/expressions";
|
|
2
|
+
import { logRetentionIdFloor } from "@vibes.diy/api-types";
|
|
3
|
+
export const PRUNE_BATCH_SIZE = 5000;
|
|
4
|
+
export const PRUNE_MAX_BATCHES = 20;
|
|
5
|
+
export async function pruneVibeLogEvents(sql, nowMs) {
|
|
6
|
+
const t = sql.tables.vibeLogEvents;
|
|
7
|
+
const prunedThrough = logRetentionIdFloor(nowMs);
|
|
8
|
+
let deleted = 0;
|
|
9
|
+
for (let batch = 0; batch < PRUNE_MAX_BATCHES; batch++) {
|
|
10
|
+
const victims = await sql.db
|
|
11
|
+
.select({ id: t.id })
|
|
12
|
+
.from(t)
|
|
13
|
+
.where(lt(t.id, prunedThrough))
|
|
14
|
+
.orderBy(asc(t.id))
|
|
15
|
+
.limit(PRUNE_BATCH_SIZE);
|
|
16
|
+
if (victims.length === 0)
|
|
17
|
+
return { deleted, prunedThrough, capped: false };
|
|
18
|
+
const lastId = victims[victims.length - 1].id;
|
|
19
|
+
await sql.db.delete(t).where(and(lt(t.id, prunedThrough), lte(t.id, lastId)));
|
|
20
|
+
deleted += victims.length;
|
|
21
|
+
if (victims.length < PRUNE_BATCH_SIZE)
|
|
22
|
+
return { deleted, prunedThrough, capped: false };
|
|
23
|
+
}
|
|
24
|
+
return { deleted, prunedThrough, capped: true };
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=prune-vibe-logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune-vibe-logs.js","sourceRoot":"","sources":["../../jsr/intern/prune-vibe-logs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAe3D,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAQrC,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAoCpC,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,GAAqB,EAAE,KAAa;IAC3E,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC;IACnC,MAAM,aAAa,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACjD,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,iBAAiB,EAAE,KAAK,EAAE,EAAE,CAAC;QAKvD,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,EAAE;aACzB,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;aACpB,IAAI,CAAC,CAAC,CAAC;aACP,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;aAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;aAClB,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAU3E,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9C,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,aAAa,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QAC9E,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;QAE1B,IAAI,OAAO,CAAC,MAAM,GAAG,gBAAgB;YAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC1F,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAClD,CAAC"}
|
|
@@ -11,6 +11,6 @@ export interface ServeRootHtmlWithSwrOpts {
|
|
|
11
11
|
readonly waitUntil: (p: Promise<unknown>) => void;
|
|
12
12
|
readonly workspaceNpmUrl?: string;
|
|
13
13
|
}
|
|
14
|
-
export declare function bareRootHtmlSwrKey(origin: string, workspaceNpmUrl: string | undefined): string;
|
|
15
|
-
export declare function pinnedRootHtmlSwrKey(origin: string, npmUrl: string): string;
|
|
14
|
+
export declare function bareRootHtmlSwrKey(origin: string, workspaceNpmUrl: string | undefined, fsId?: string): string;
|
|
15
|
+
export declare function pinnedRootHtmlSwrKey(origin: string, npmUrl: string, fsId?: string): string;
|
|
16
16
|
export declare function serveRootHtmlWithSwr(opts: ServeRootHtmlWithSwrOpts): Promise<Response>;
|
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import { CACHEABLE_MARKER_HEADER, CACHED_AT_HEADER, CACHE_STATE_HEADER, cachedAtOf, canonicalWorkspacePin, fromStoredResponse, isPlatformWorkspaceNpmUrl, swrDecision, toCacheableStoredResponse, } from "./swr-html-cache.js";
|
|
1
|
+
import { CACHEABLE_MARKER_HEADER, CACHED_AT_HEADER, CACHE_STATE_HEADER, cachedAtOf, canonicalWorkspacePin, fromStoredResponse, isPlatformWorkspaceNpmUrl, swrDecision, toCacheableStoredResponse, UNVERSIONED_CLIENT_CACHE_CONTROL, VERSIONED_CLIENT_CACHE_CONTROL, } from "./swr-html-cache.js";
|
|
2
2
|
import { ROOT_HTML_CACHE_CONTRACT } from "./root-html-cache-contract.js";
|
|
3
3
|
import { isTrackingParam } from "@vibes.diy/api-types";
|
|
4
4
|
import { etagMatches } from "../public/etag-utils.js";
|
|
5
|
-
export function bareRootHtmlSwrKey(origin, workspaceNpmUrl) {
|
|
6
|
-
return `${origin}/?vibes-root-swr=ws-${encodeURIComponent(workspaceNpmUrl ?? "")}`;
|
|
5
|
+
export function bareRootHtmlSwrKey(origin, workspaceNpmUrl, fsId) {
|
|
6
|
+
return `${origin}${versionedKeyPrefix(fsId)}/?vibes-root-swr=ws-${encodeURIComponent(workspaceNpmUrl ?? "")}`;
|
|
7
7
|
}
|
|
8
|
-
|
|
9
|
-
return
|
|
8
|
+
function versionedKeyPrefix(fsId) {
|
|
9
|
+
return fsId === undefined ? "" : `/~${fsId}~`;
|
|
10
|
+
}
|
|
11
|
+
function versionedRootFsId(pathname) {
|
|
12
|
+
return /^\/~(z[a-zA-Z0-9]{8,})~(?:\/(?:index\.html)?)?$/.exec(pathname)?.[1];
|
|
13
|
+
}
|
|
14
|
+
export function pinnedRootHtmlSwrKey(origin, npmUrl, fsId) {
|
|
15
|
+
return `${origin}${versionedKeyPrefix(fsId)}/?npmUrl=${encodeURIComponent(canonicalWorkspacePin(npmUrl))}&contract=${ROOT_HTML_CACHE_CONTRACT}`;
|
|
10
16
|
}
|
|
11
17
|
const VIBE_PROTOCOL_PARAM = "vibesProto";
|
|
12
18
|
function eligibleKey(req, workspaceNpmUrl) {
|
|
@@ -17,13 +23,14 @@ function eligibleKey(req, workspaceNpmUrl) {
|
|
|
17
23
|
if ((req.headers.get("Cookie") ?? "").includes("Vibes-Npm-Url"))
|
|
18
24
|
return undefined;
|
|
19
25
|
const url = new URL(req.url);
|
|
20
|
-
|
|
26
|
+
const fsId = versionedRootFsId(url.pathname);
|
|
27
|
+
if (fsId === undefined && url.pathname !== "/" && url.pathname !== "/index.html")
|
|
21
28
|
return undefined;
|
|
22
29
|
const params = [...url.searchParams];
|
|
23
30
|
if (params.some(([name]) => isTrackingParam(name)))
|
|
24
31
|
return undefined;
|
|
25
32
|
if (params.length === 0)
|
|
26
|
-
return bareRootHtmlSwrKey(url.origin, workspaceNpmUrl);
|
|
33
|
+
return bareRootHtmlSwrKey(url.origin, workspaceNpmUrl, fsId);
|
|
27
34
|
let npmUrl;
|
|
28
35
|
let seenProto = false;
|
|
29
36
|
for (const [name, value] of params) {
|
|
@@ -45,7 +52,7 @@ function eligibleKey(req, workspaceNpmUrl) {
|
|
|
45
52
|
return undefined;
|
|
46
53
|
if (workspaceNpmUrl === undefined || !isPlatformWorkspaceNpmUrl(npmUrl, workspaceNpmUrl))
|
|
47
54
|
return undefined;
|
|
48
|
-
return pinnedRootHtmlSwrKey(url.origin, npmUrl);
|
|
55
|
+
return pinnedRootHtmlSwrKey(url.origin, npmUrl, fsId);
|
|
49
56
|
}
|
|
50
57
|
function refreshRequest(req) {
|
|
51
58
|
const headers = new Headers(req.headers);
|
|
@@ -74,6 +81,8 @@ export async function serveRootHtmlWithSwr(opts) {
|
|
|
74
81
|
const key = eligibleKey(opts.request, opts.workspaceNpmUrl);
|
|
75
82
|
if (key === undefined)
|
|
76
83
|
return opts.inner(opts.request);
|
|
84
|
+
const isVersionedRoot = versionedRootFsId(new URL(opts.request.url).pathname) !== undefined;
|
|
85
|
+
const clientCacheControl = isVersionedRoot ? VERSIONED_CLIENT_CACHE_CONTROL : UNVERSIONED_CLIENT_CACHE_CONTROL;
|
|
77
86
|
const cached = await opts.cache.match(key);
|
|
78
87
|
if (cached !== undefined) {
|
|
79
88
|
const state = swrDecision({ cachedAt: cachedAtOf(cached), now: opts.now() });
|
|
@@ -83,13 +92,17 @@ export async function serveRootHtmlWithSwr(opts) {
|
|
|
83
92
|
}
|
|
84
93
|
const serveState = state === "fresh" ? "hit-fresh" : "hit-stale-refreshing";
|
|
85
94
|
if (wants304(opts.request, cached.headers.get("ETag"))) {
|
|
86
|
-
const h = new Headers({
|
|
95
|
+
const h = new Headers({
|
|
96
|
+
"Cache-Control": clientCacheControl,
|
|
97
|
+
[CACHE_STATE_HEADER]: serveState,
|
|
98
|
+
"Access-Control-Allow-Origin": "*",
|
|
99
|
+
});
|
|
87
100
|
const etag = cached.headers.get("ETag");
|
|
88
101
|
if (etag !== null)
|
|
89
102
|
h.set("ETag", etag);
|
|
90
103
|
return new Response(null, { status: 304, headers: h });
|
|
91
104
|
}
|
|
92
|
-
return fromStoredResponse(cached, serveState);
|
|
105
|
+
return fromStoredResponse(cached, serveState, clientCacheControl);
|
|
93
106
|
}
|
|
94
107
|
}
|
|
95
108
|
const res = await renderAndStore(opts, key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"swr-html-cache-orchestrator.js","sourceRoot":"","sources":["../../jsr/intern/swr-html-cache-orchestrator.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,kBAAkB,EAClB,UAAU,EACV,qBAAqB,EACrB,kBAAkB,EAClB,yBAAyB,EACzB,WAAW,EACX,yBAAyB,
|
|
1
|
+
{"version":3,"file":"swr-html-cache-orchestrator.js","sourceRoot":"","sources":["../../jsr/intern/swr-html-cache-orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,8 +9,10 @@ export declare function swrDecision(opts: {
|
|
|
9
9
|
readonly cachedAt: number;
|
|
10
10
|
readonly now: number;
|
|
11
11
|
}): SwrState;
|
|
12
|
+
export declare const UNVERSIONED_CLIENT_CACHE_CONTROL = "public, no-cache, must-revalidate";
|
|
13
|
+
export declare const VERSIONED_CLIENT_CACHE_CONTROL = "public, max-age=86400";
|
|
12
14
|
export declare function toCacheableStoredResponse(res: Response, now: number): Response | undefined;
|
|
13
|
-
export declare function fromStoredResponse(stored: Response, state: CacheServeState): Response;
|
|
15
|
+
export declare function fromStoredResponse(stored: Response, state: CacheServeState, clientCacheControl?: string): Response;
|
|
14
16
|
export declare function cachedAtOf(stored: Response): number;
|
|
15
17
|
export declare function isPlatformWorkspaceNpmUrl(candidate: string, workspace: string): boolean;
|
|
16
18
|
export declare function canonicalWorkspacePin(npmUrl: string): string;
|
package/intern/swr-html-cache.js
CHANGED
|
@@ -12,7 +12,8 @@ export function swrDecision(opts) {
|
|
|
12
12
|
return "fresh";
|
|
13
13
|
return "stale";
|
|
14
14
|
}
|
|
15
|
-
const
|
|
15
|
+
export const UNVERSIONED_CLIENT_CACHE_CONTROL = "public, no-cache, must-revalidate";
|
|
16
|
+
export const VERSIONED_CLIENT_CACHE_CONTROL = "public, max-age=86400";
|
|
16
17
|
const STORED_CACHE_CONTROL = "public, s-maxage=86400";
|
|
17
18
|
export function toCacheableStoredResponse(res, now) {
|
|
18
19
|
if (res.status !== 200)
|
|
@@ -28,10 +29,10 @@ export function toCacheableStoredResponse(res, now) {
|
|
|
28
29
|
headers.set("Cache-Control", STORED_CACHE_CONTROL);
|
|
29
30
|
return new Response(res.body, { status: res.status, headers });
|
|
30
31
|
}
|
|
31
|
-
export function fromStoredResponse(stored, state) {
|
|
32
|
+
export function fromStoredResponse(stored, state, clientCacheControl = UNVERSIONED_CLIENT_CACHE_CONTROL) {
|
|
32
33
|
const headers = new Headers(stored.headers);
|
|
33
34
|
headers.delete(CACHED_AT_HEADER);
|
|
34
|
-
headers.set("Cache-Control",
|
|
35
|
+
headers.set("Cache-Control", clientCacheControl);
|
|
35
36
|
headers.set(CACHE_STATE_HEADER, state);
|
|
36
37
|
return new Response(stored.body, { status: stored.status, headers });
|
|
37
38
|
}
|