target-supabase-sdk 0.2.12 → 0.2.13
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/browser.d.ts +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +1 -1
- package/dist/chunks/enable-DqnfLPsQ.js +874 -0
- package/dist/chunks/enable-DqnfLPsQ.js.map +1 -0
- package/dist/chunks/list.api-BzbTJBsM.js.map +1 -1
- package/dist/chunks/{task-queue-H4mpSW8R.js → task-queue-6X3aglJh.js} +108 -3
- package/dist/chunks/task-queue-6X3aglJh.js.map +1 -0
- package/dist/node/preload/run-service-preload.d.ts.map +1 -1
- package/dist/node/preload/service-preload.interface.d.ts +3 -1
- package/dist/node/preload/service-preload.interface.d.ts.map +1 -1
- package/dist/node/process/managed-child-processes.d.ts.map +1 -1
- package/dist/node/service-guard/service-guard-node.d.ts.map +1 -1
- package/dist/node/service-host/index.d.ts +1 -0
- package/dist/node/service-host/index.d.ts.map +1 -1
- package/dist/node/service-host/service-host.d.ts +5 -1
- package/dist/node/service-host/service-host.d.ts.map +1 -1
- package/dist/node.d.ts +10 -5
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +492 -47
- package/dist/node.js.map +1 -1
- package/dist/preload.js +9 -6
- package/dist/preload.js.map +1 -1
- package/dist/service/index.d.ts +2 -2
- package/dist/service/index.d.ts.map +1 -1
- package/dist/service/registry.service.d.ts +19 -0
- package/dist/service/registry.service.d.ts.map +1 -1
- package/dist/shared/log/core/create-logger.d.ts.map +1 -0
- package/dist/shared/log/{log-batch.d.ts → core/log-batch.d.ts} +4 -4
- package/dist/shared/log/core/log-batch.d.ts.map +1 -0
- package/dist/shared/log/core/log-manager.d.ts.map +1 -0
- package/dist/shared/log/core/log-min-level.d.ts.map +1 -0
- package/dist/shared/log/core/log-scope.d.ts.map +1 -0
- package/dist/shared/log/index.d.ts +13 -13
- package/dist/shared/log/index.d.ts.map +1 -1
- package/dist/shared/log/spool/collector.d.ts +21 -0
- package/dist/shared/log/spool/collector.d.ts.map +1 -0
- package/dist/shared/log/spool/config.d.ts +7 -0
- package/dist/shared/log/spool/config.d.ts.map +1 -0
- package/dist/shared/log/spool/coordinator.d.ts +18 -0
- package/dist/shared/log/spool/coordinator.d.ts.map +1 -0
- package/dist/shared/log/spool/enable.d.ts +23 -0
- package/dist/shared/log/spool/enable.d.ts.map +1 -0
- package/dist/shared/log/spool/file.d.ts +21 -0
- package/dist/shared/log/spool/file.d.ts.map +1 -0
- package/dist/shared/log/spool/interface.d.ts +55 -0
- package/dist/shared/log/spool/interface.d.ts.map +1 -0
- package/dist/shared/log/spool/paths.d.ts +6 -0
- package/dist/shared/log/spool/paths.d.ts.map +1 -0
- package/dist/shared/log/spool/process-roles.d.ts +17 -0
- package/dist/shared/log/spool/process-roles.d.ts.map +1 -0
- package/dist/shared/log/spool/register-collect-log-runner.d.ts +15 -0
- package/dist/shared/log/spool/register-collect-log-runner.d.ts.map +1 -0
- package/dist/shared/log/spool/service-lifecycle.d.ts +13 -0
- package/dist/shared/log/spool/service-lifecycle.d.ts.map +1 -0
- package/dist/shared/log/spool/writer.d.ts +32 -0
- package/dist/shared/log/spool/writer.d.ts.map +1 -0
- package/dist/shared/log/{log-persist-batch-id.d.ts → upload/batch-id.d.ts} +3 -3
- package/dist/shared/log/upload/batch-id.d.ts.map +1 -0
- package/dist/shared/log/upload/env.d.ts +7 -0
- package/dist/shared/log/upload/env.d.ts.map +1 -0
- package/dist/shared/log/{log-persist-flush.d.ts → upload/flush.d.ts} +3 -3
- package/dist/shared/log/upload/flush.d.ts.map +1 -0
- package/dist/shared/log/{log-persist-hook.d.ts → upload/hook.d.ts} +2 -2
- package/dist/shared/log/upload/hook.d.ts.map +1 -0
- package/dist/shared/log/upload/interface.d.ts +33 -0
- package/dist/shared/log/upload/interface.d.ts.map +1 -0
- package/dist/shared/log/upload/logger.d.ts +22 -0
- package/dist/shared/log/upload/logger.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/browser.ts +1 -0
- package/src/node/preload/run-service-preload.ts +11 -6
- package/src/node/preload/service-preload.interface.ts +3 -1
- package/src/node/process/create-managed-child-processes.ts +1 -1
- package/src/node/process/managed-child-processes.ts +8 -1
- package/src/node/service-guard/service-guard-node.ts +5 -0
- package/src/node/service-host/index.ts +4 -0
- package/src/node/service-host/service-host.ts +22 -3
- package/src/node.ts +26 -19
- package/src/service/index.ts +3 -0
- package/src/service/registry.service.ts +142 -0
- package/src/shared/log/README.md +206 -0
- package/src/shared/log/{log-batch.ts → core/log-batch.ts} +4 -4
- package/src/shared/log/{log-manager.ts → core/log-manager.ts} +3 -3
- package/src/shared/log/{log-min-level.ts → core/log-min-level.ts} +1 -1
- package/src/shared/log/{log-scope.ts → core/log-scope.ts} +1 -1
- package/src/shared/log/index.ts +13 -18
- package/src/shared/log/spool/collector.ts +330 -0
- package/src/shared/log/spool/config.ts +56 -0
- package/src/shared/log/spool/coordinator.ts +55 -0
- package/src/shared/log/spool/enable.ts +136 -0
- package/src/shared/log/spool/file.ts +75 -0
- package/src/shared/log/spool/interface.ts +62 -0
- package/src/shared/log/spool/paths.ts +30 -0
- package/src/shared/log/spool/process-roles.ts +75 -0
- package/src/shared/log/spool/register-collect-log-runner.ts +63 -0
- package/src/shared/log/spool/service-lifecycle.ts +35 -0
- package/src/shared/log/spool/writer.ts +273 -0
- package/src/shared/log/{log-persist-batch-id.ts → upload/batch-id.ts} +2 -2
- package/src/shared/log/upload/env.ts +26 -0
- package/src/shared/log/{log-persist-flush.ts → upload/flush.ts} +8 -7
- package/src/shared/log/{log-persist-hook.ts → upload/hook.ts} +1 -1
- package/src/shared/log/upload/interface.ts +38 -0
- package/src/shared/log/upload/logger.ts +37 -0
- package/dist/chunks/enable-log-persist-Dl55_mv2.js +0 -1674
- package/dist/chunks/enable-log-persist-Dl55_mv2.js.map +0 -1
- package/dist/chunks/task-queue-H4mpSW8R.js.map +0 -1
- package/dist/shared/log/create-logger.d.ts.map +0 -1
- package/dist/shared/log/enable-log-persist.d.ts +0 -28
- package/dist/shared/log/enable-log-persist.d.ts.map +0 -1
- package/dist/shared/log/log-batch.d.ts.map +0 -1
- package/dist/shared/log/log-manager.d.ts.map +0 -1
- package/dist/shared/log/log-min-level.d.ts.map +0 -1
- package/dist/shared/log/log-persist-batch-id.d.ts.map +0 -1
- package/dist/shared/log/log-persist-coordinator.d.ts +0 -37
- package/dist/shared/log/log-persist-coordinator.d.ts.map +0 -1
- package/dist/shared/log/log-persist-errors.d.ts +0 -4
- package/dist/shared/log/log-persist-errors.d.ts.map +0 -1
- package/dist/shared/log/log-persist-flush.d.ts.map +0 -1
- package/dist/shared/log/log-persist-hook.d.ts.map +0 -1
- package/dist/shared/log/log-persist-logger.d.ts +0 -16
- package/dist/shared/log/log-persist-logger.d.ts.map +0 -1
- package/dist/shared/log/log-persist-registry.d.ts +0 -18
- package/dist/shared/log/log-persist-registry.d.ts.map +0 -1
- package/dist/shared/log/log-persist.config.d.ts +0 -9
- package/dist/shared/log/log-persist.config.d.ts.map +0 -1
- package/dist/shared/log/log-persist.d.ts +0 -62
- package/dist/shared/log/log-persist.d.ts.map +0 -1
- package/dist/shared/log/log-persist.interface.d.ts +0 -132
- package/dist/shared/log/log-persist.interface.d.ts.map +0 -1
- package/dist/shared/log/log-scope.d.ts.map +0 -1
- package/src/shared/log/enable-log-persist.ts +0 -225
- package/src/shared/log/log-persist-coordinator.ts +0 -107
- package/src/shared/log/log-persist-errors.ts +0 -16
- package/src/shared/log/log-persist-logger.ts +0 -61
- package/src/shared/log/log-persist-registry.ts +0 -252
- package/src/shared/log/log-persist.config.ts +0 -115
- package/src/shared/log/log-persist.interface.ts +0 -150
- package/src/shared/log/log-persist.ts +0 -822
- /package/dist/shared/log/{create-logger.d.ts → core/create-logger.d.ts} +0 -0
- /package/dist/shared/log/{log-manager.d.ts → core/log-manager.d.ts} +0 -0
- /package/dist/shared/log/{log-min-level.d.ts → core/log-min-level.d.ts} +0 -0
- /package/dist/shared/log/{log-scope.d.ts → core/log-scope.d.ts} +0 -0
- /package/src/shared/log/{create-logger.ts → core/create-logger.ts} +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { TargetDraft } from "../../../core.interface";
|
|
2
|
+
import type { List } from "../../../list/list.interface";
|
|
3
|
+
import type { LogEntry } from "../core/log-manager";
|
|
4
|
+
/**
|
|
5
|
+
* `ListDetails.loaderKey` stamped on every persisted log batch (write + read side).
|
|
6
|
+
* Business type: **LogBatch** (transport flush). Pairs with log-service **LogTrace**
|
|
7
|
+
* (`LogTrace.0`) after rekeying by `traceId`.
|
|
8
|
+
*/
|
|
9
|
+
export declare const LOG_PERSIST_LOADER_KEY = "LogBatch.0";
|
|
10
|
+
/** Alias for {@link LOG_PERSIST_LOADER_KEY} — preferred when contrasting with LogTrace. */
|
|
11
|
+
export declare const LOG_BATCH_LOADER_KEY = "LogBatch.0";
|
|
12
|
+
/** Legacy transport metadata — fixed `"slow"` for spool uploads; required for downstream decode today. */
|
|
13
|
+
export type LogPersistLane = "fast" | "medium" | "slow";
|
|
14
|
+
export interface LogBatchMeta {
|
|
15
|
+
service: string;
|
|
16
|
+
process: string;
|
|
17
|
+
pid: number;
|
|
18
|
+
lane: LogPersistLane;
|
|
19
|
+
count: number;
|
|
20
|
+
from: number | null;
|
|
21
|
+
to: number | null;
|
|
22
|
+
flushedAt: number;
|
|
23
|
+
idempotencyKey: string;
|
|
24
|
+
}
|
|
25
|
+
export interface BuildLogListDraftInput {
|
|
26
|
+
service: string;
|
|
27
|
+
process: string;
|
|
28
|
+
lane: LogPersistLane;
|
|
29
|
+
idempotencyKey: string;
|
|
30
|
+
entries: LogEntry[];
|
|
31
|
+
}
|
|
32
|
+
export type LogListDraft = TargetDraft<List>;
|
|
33
|
+
//# sourceMappingURL=interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../../../src/shared/log/upload/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,eAAe,CAAC;AAEnD,2FAA2F;AAC3F,eAAO,MAAM,oBAAoB,eAAyB,CAAC;AAE3D,0GAA0G;AAC1G,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,YAAY;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,cAAc,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** User-facing / lifecycle logs — may be persisted like normal app logs. */
|
|
2
|
+
export declare const LOG_PERSIST_TOPIC = "log-persist";
|
|
3
|
+
/** Operational logs from the persist pipeline — never re-offered to avoid feedback loops. */
|
|
4
|
+
export declare const LOG_PERSIST_INTERNAL_TOPIC = "log-persist-internal";
|
|
5
|
+
type PipelineLogData = Record<string, unknown>;
|
|
6
|
+
/** Supabase upload path (`postLogBatch`). */
|
|
7
|
+
export declare const persistLogger: {
|
|
8
|
+
debug: (message: string, data?: PipelineLogData) => void;
|
|
9
|
+
info: (message: string, data?: PipelineLogData) => void;
|
|
10
|
+
warn: (message: string, data?: PipelineLogData) => void;
|
|
11
|
+
error: (message: string, data?: PipelineLogData) => void;
|
|
12
|
+
};
|
|
13
|
+
/** File spool writer + collector. */
|
|
14
|
+
export declare const spoolLogger: {
|
|
15
|
+
debug: (message: string, data?: PipelineLogData) => void;
|
|
16
|
+
info: (message: string, data?: PipelineLogData) => void;
|
|
17
|
+
warn: (message: string, data?: PipelineLogData) => void;
|
|
18
|
+
error: (message: string, data?: PipelineLogData) => void;
|
|
19
|
+
};
|
|
20
|
+
export declare function isLogPersistInternalTopic(topic: string | undefined): boolean;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../../src/shared/log/upload/logger.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAE/C,6FAA6F;AAC7F,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AAEjE,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAoB/C,6CAA6C;AAC7C,eAAO,MAAM,aAAa;qBARD,MAAM,SAAS,eAAe;oBAC/B,MAAM,SAAS,eAAe;oBAC9B,MAAM,SAAS,eAAe;qBAC7B,MAAM,SAAS,eAAe;CAKQ,CAAC;AAEhE,qCAAqC;AACrC,eAAO,MAAM,WAAW;qBAXC,MAAM,SAAS,eAAe;oBAC/B,MAAM,SAAS,eAAe;oBAC9B,MAAM,SAAS,eAAe;qBAC7B,MAAM,SAAS,eAAe;CAQK,CAAC;AAE7D,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAE5E"}
|
package/package.json
CHANGED
package/src/browser.ts
CHANGED
|
@@ -171,6 +171,7 @@ export {
|
|
|
171
171
|
registerServiceAtStartup,
|
|
172
172
|
registrySlotRuntimePatchFromGuardResult,
|
|
173
173
|
releaseSystemRegistrySlots,
|
|
174
|
+
releaseSystemRegistrySlotsByServiceId,
|
|
174
175
|
resetSystemRegistryConfig,
|
|
175
176
|
resetSystemRegistryConfigSchema,
|
|
176
177
|
resolveActiveRegistryServiceId,
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { logManager } from "../../shared/log/core/log-manager";
|
|
3
|
+
import { resolveLogMinLevel } from "../../shared/log/core/log-min-level";
|
|
4
|
+
import { validateLogSpoolPreloadEnv } from "../../shared/log/spool/enable";
|
|
5
|
+
import { mergeLogSpoolExtraProcessRolesEnv } from "../../shared/log/spool/process-roles";
|
|
6
|
+
import { logSpoolEnabledFromEnv } from "../../shared/log/upload/env";
|
|
6
7
|
import { loadEnvFiles, pinEnvProfileFromArgv } from "../env/load-env";
|
|
7
8
|
import { resolveProjectRootByPackageName } from "../env/project-root";
|
|
8
9
|
import type { ServicePreloadOptions } from "./service-preload.interface";
|
|
9
10
|
|
|
10
11
|
function applyServiceEnvDefaults(projectRoot: string, options: ServicePreloadOptions): void {
|
|
11
|
-
if (!
|
|
12
|
+
if (!logSpoolEnabledFromEnv()) {
|
|
12
13
|
return;
|
|
13
14
|
}
|
|
14
15
|
|
|
@@ -22,6 +23,10 @@ function applyServiceEnvDefaults(projectRoot: string, options: ServicePreloadOpt
|
|
|
22
23
|
const relative = options.runtimeDataDirRelative ?? "data/runtime";
|
|
23
24
|
process.env.RUNTIME_DATA_DIR = resolve(projectRoot, relative);
|
|
24
25
|
}
|
|
26
|
+
|
|
27
|
+
if (options.logSpoolExtraProcessRoles != null && options.logSpoolExtraProcessRoles.length > 0) {
|
|
28
|
+
mergeLogSpoolExtraProcessRolesEnv(process.env, options.logSpoolExtraProcessRoles);
|
|
29
|
+
}
|
|
25
30
|
}
|
|
26
31
|
|
|
27
32
|
function applyLogMinLevelFromEnv(options: ServicePreloadOptions): void {
|
|
@@ -56,7 +61,7 @@ export function runServicePreload(options: ServicePreloadOptions): void {
|
|
|
56
61
|
|
|
57
62
|
applyLogMinLevelFromEnv(options);
|
|
58
63
|
|
|
59
|
-
|
|
64
|
+
validateLogSpoolPreloadEnv();
|
|
60
65
|
|
|
61
66
|
// TODO: Phase 5 — optional unhandledRejection / uncaughtException formatters
|
|
62
67
|
// (formerly watch-service preload-diagnostics.mjs)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { LogLevel } from "../../shared/log/log-manager";
|
|
1
|
+
import type { LogLevel } from "../../shared/log/core/log-manager";
|
|
2
2
|
|
|
3
3
|
export interface ServicePreloadOptions {
|
|
4
4
|
/** `import.meta.url` from the service `scripts/preload.mjs`. */
|
|
@@ -17,4 +17,6 @@ export interface ServicePreloadOptions {
|
|
|
17
17
|
defaultLogMinLevel?: LogLevel;
|
|
18
18
|
/** Apply `logManager.setOptions({ minLevel })` from env (default true). */
|
|
19
19
|
applyLogMinLevel?: boolean;
|
|
20
|
+
/** Extra spool roles beyond main|guard|scheduler|worker (e.g. `chrome-sidecar`). Merged into `LOG_SPOOL_EXTRA_PROCESS_ROLES`. */
|
|
21
|
+
logSpoolExtraProcessRoles?: readonly string[];
|
|
20
22
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createLogger } from "../../shared/log/create-logger";
|
|
1
|
+
import { createLogger } from "../../shared/log/core/create-logger";
|
|
2
2
|
import type { ManagedChildProcessesOptions } from "./managed-child-processes";
|
|
3
3
|
import { ManagedChildProcesses } from "./managed-child-processes";
|
|
4
4
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ChildProcess } from "node:child_process";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import type { LoggerWithScope } from "../../shared/log";
|
|
4
|
+
import { resolveLogSpoolSpawnEnvForLabel } from "../../shared/log/spool/enable";
|
|
4
5
|
import { isChildProcessRunning, spawnTsxChild } from "./process-spawn";
|
|
5
6
|
|
|
6
7
|
export interface ManagedChildProcessesOptions {
|
|
@@ -80,12 +81,18 @@ export class ManagedChildProcesses {
|
|
|
80
81
|
return { child: existing, created: false };
|
|
81
82
|
}
|
|
82
83
|
|
|
84
|
+
const logSpoolEnv = resolveLogSpoolSpawnEnvForLabel(label);
|
|
85
|
+
const childEnv =
|
|
86
|
+
spawnOptions?.env != null
|
|
87
|
+
? { ...process.env, ...logSpoolEnv, ...spawnOptions.env }
|
|
88
|
+
: { ...process.env, ...logSpoolEnv };
|
|
89
|
+
|
|
83
90
|
const child = spawnTsxChild({
|
|
84
91
|
projectRoot: this.projectRoot,
|
|
85
92
|
entryScript,
|
|
86
93
|
preloadModules: this.preloadModules,
|
|
87
94
|
useTsx: spawnOptions?.useTsx ?? this.defaultUseTsx,
|
|
88
|
-
env:
|
|
95
|
+
env: childEnv,
|
|
89
96
|
});
|
|
90
97
|
|
|
91
98
|
child.on("exit", (code: number | null, signal: NodeJS.Signals | null) => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { LoggerWithScope } from "../../shared/log";
|
|
2
|
+
import { registerCollectLogRunner } from "../../shared/log/spool/register-collect-log-runner";
|
|
2
3
|
import { TriggerNode } from "../../trigger/trigger-node";
|
|
3
4
|
import { registerServiceGuardRunner } from "./register-service-guard-runner";
|
|
4
5
|
import { runReadinessGate } from "./run-readiness-gate";
|
|
@@ -28,6 +29,10 @@ class ServiceGuardNode extends TriggerNode {
|
|
|
28
29
|
logTopic: options.logTopic,
|
|
29
30
|
...options.guardRunner,
|
|
30
31
|
});
|
|
32
|
+
registerCollectLogRunner({
|
|
33
|
+
serviceValue: options.serviceValue,
|
|
34
|
+
getServiceId: options.guardRunner.getServiceId,
|
|
35
|
+
});
|
|
31
36
|
return new ServiceGuardNode(options);
|
|
32
37
|
}
|
|
33
38
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { createLogger, type Service, ServiceRegistryError } from "../../browser";
|
|
2
2
|
import { claimServiceRegistrySlot, type ServiceRegistrySession } from "../../service/registry-lifecycle";
|
|
3
3
|
import type { LoggerWithScope } from "../../shared/log";
|
|
4
|
+
import { LOG_SPOOL_SERVICE_ID_ENV } from "../../shared/log/spool/config";
|
|
5
|
+
import { ensureLogSpoolFromEnv } from "../../shared/log/spool/enable";
|
|
6
|
+
import { logSpoolEnabledFromEnv } from "../../shared/log/upload/env";
|
|
4
7
|
import type { ManagedChildProcesses } from "../process/managed-child-processes";
|
|
5
8
|
|
|
6
9
|
export interface ServiceHostClosable {
|
|
@@ -10,6 +13,8 @@ export interface ServiceHostClosable {
|
|
|
10
13
|
export interface ServiceHostContext {
|
|
11
14
|
service: Service;
|
|
12
15
|
session: ServiceRegistrySession;
|
|
16
|
+
/** Registry instance id — same as `service.id`; children inherit via spawn env injection. */
|
|
17
|
+
serviceId: string;
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
export interface ServiceHostOptions {
|
|
@@ -23,9 +28,11 @@ export interface ServiceHostOptions {
|
|
|
23
28
|
prepare?: () => Promise<void>;
|
|
24
29
|
createInstance: () => Promise<Service | { service: Service; baseUrl?: string }>;
|
|
25
30
|
onRegistryClaimed?: (ctx: ServiceHostContext) => Promise<void>;
|
|
26
|
-
startSupervisors?: () => void | Promise<void>;
|
|
31
|
+
startSupervisors?: (ctx: ServiceHostContext) => void | Promise<void>;
|
|
27
32
|
waitUntilReady?: () => Promise<void>;
|
|
28
33
|
startServer?: () => Promise<ServiceHostClosable>;
|
|
34
|
+
/** When true (default), enable file log spool for main after registry claim. */
|
|
35
|
+
enableLogSpoolAfterClaim?: boolean;
|
|
29
36
|
/** Stop child processes and other local resources (not registry release). */
|
|
30
37
|
onShutdown?: (signal: string) => Promise<void>;
|
|
31
38
|
}
|
|
@@ -121,12 +128,24 @@ export function createServiceHost(options: ServiceHostOptions): ServiceHost {
|
|
|
121
128
|
throw error;
|
|
122
129
|
}
|
|
123
130
|
|
|
131
|
+
const hostCtx: ServiceHostContext = { service: session.service, session, serviceId: session.service.id };
|
|
132
|
+
|
|
124
133
|
if (options.onRegistryClaimed != null) {
|
|
125
|
-
await options.onRegistryClaimed(
|
|
134
|
+
await options.onRegistryClaimed(hostCtx);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const enableSpool = options.enableLogSpoolAfterClaim ?? true;
|
|
138
|
+
if (enableSpool && logSpoolEnabledFromEnv()) {
|
|
139
|
+
process.env[LOG_SPOOL_SERVICE_ID_ENV] = session.service.id;
|
|
140
|
+
await ensureLogSpoolFromEnv({
|
|
141
|
+
serviceId: session.service.id,
|
|
142
|
+
serviceValue: options.serviceValue,
|
|
143
|
+
processRole: "main",
|
|
144
|
+
});
|
|
126
145
|
}
|
|
127
146
|
|
|
128
147
|
if (options.startSupervisors != null) {
|
|
129
|
-
await options.startSupervisors();
|
|
148
|
+
await options.startSupervisors(hostCtx);
|
|
130
149
|
}
|
|
131
150
|
|
|
132
151
|
if (options.waitUntilReady != null) {
|
package/src/node.ts
CHANGED
|
@@ -122,9 +122,11 @@ export type {
|
|
|
122
122
|
} from "./node/service-host";
|
|
123
123
|
export {
|
|
124
124
|
applyRegistrySlotGuardStep,
|
|
125
|
+
COLLECT_LOG_RUNNER_KEY,
|
|
125
126
|
createServiceHost,
|
|
126
127
|
getWorkerSpawnCooldownLastAt,
|
|
127
128
|
markWorkerSpawned,
|
|
129
|
+
registerCollectLogRunner,
|
|
128
130
|
registerServiceGuardRunner,
|
|
129
131
|
runReadinessGate,
|
|
130
132
|
runServiceGuardTick,
|
|
@@ -133,27 +135,32 @@ export {
|
|
|
133
135
|
ServiceGuardNode,
|
|
134
136
|
} from "./node/service-host";
|
|
135
137
|
export { RepoManager } from "./repo/repo-manager";
|
|
138
|
+
export { runCollectLogTick } from "./shared/log/spool/collector";
|
|
139
|
+
export { LOG_SPOOL_SERVICE_ID_ENV } from "./shared/log/spool/config";
|
|
140
|
+
export type { LogSpoolCoordinator, LogSpoolCoordinatorOptions } from "./shared/log/spool/coordinator";
|
|
141
|
+
export { createLogSpoolCoordinator } from "./shared/log/spool/coordinator";
|
|
136
142
|
export {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
validateLogPersistPreloadEnv,
|
|
145
|
-
waitForLogPersistReady,
|
|
146
|
-
} from "./shared/log/enable-log-persist";
|
|
143
|
+
buildLogSpoolSpawnEnv,
|
|
144
|
+
ensureLogSpoolFromEnv,
|
|
145
|
+
getLogSpoolStats,
|
|
146
|
+
logSpoolEnabledFromEnv,
|
|
147
|
+
shutdownLogSpoolFromEnv,
|
|
148
|
+
validateLogSpoolPreloadEnv,
|
|
149
|
+
} from "./shared/log/spool/enable";
|
|
147
150
|
export type {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
151
|
+
EnableLogSpoolOptions,
|
|
152
|
+
LogSpoolCoreProcessRole,
|
|
153
|
+
LogSpoolProcessRole,
|
|
154
|
+
LogSpoolWriterStats,
|
|
155
|
+
} from "./shared/log/spool/interface";
|
|
156
|
+
export { resolveLogSpoolRoot } from "./shared/log/spool/paths";
|
|
157
|
+
export {
|
|
158
|
+
enableLogSpoolFromEnvInChild,
|
|
159
|
+
getMainLogSpoolWriterStats,
|
|
160
|
+
isLogSpoolEnabled,
|
|
161
|
+
shutdownLogSpool,
|
|
162
|
+
} from "./shared/log/spool/service-lifecycle";
|
|
163
|
+
export type { LogBatchMeta, LogPersistLane } from "./shared/log/upload/interface";
|
|
157
164
|
export type {
|
|
158
165
|
ConfigSchema,
|
|
159
166
|
LoadCachedJsConfigOptions,
|
package/src/service/index.ts
CHANGED
|
@@ -35,6 +35,8 @@ export type {
|
|
|
35
35
|
PatchServiceRuntimeInput,
|
|
36
36
|
RegisterServiceInput,
|
|
37
37
|
ReleasedRegistrySlot,
|
|
38
|
+
ReleaseSystemRegistrySlotsByServiceIdInput,
|
|
39
|
+
ReleaseSystemRegistrySlotsByServiceIdOutcome,
|
|
38
40
|
ReleaseSystemRegistrySlotsInput,
|
|
39
41
|
ReleaseSystemRegistrySlotsOutcome,
|
|
40
42
|
TargetSystemRegistrySlotView,
|
|
@@ -51,6 +53,7 @@ export {
|
|
|
51
53
|
registerService,
|
|
52
54
|
registerServiceAtStartup,
|
|
53
55
|
releaseSystemRegistrySlots,
|
|
56
|
+
releaseSystemRegistrySlotsByServiceId,
|
|
54
57
|
resolveActiveRegistryServiceId,
|
|
55
58
|
ServiceRegistryError,
|
|
56
59
|
unregisterService,
|
|
@@ -58,6 +58,13 @@ export interface ReleaseSystemRegistrySlotsInput {
|
|
|
58
58
|
maxAttempts?: number;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
export interface ReleaseSystemRegistrySlotsByServiceIdInput {
|
|
62
|
+
/** Runtime Service row ids bound to ACTIVE slots (one slot per id). */
|
|
63
|
+
serviceIds: string[];
|
|
64
|
+
traceId?: string;
|
|
65
|
+
maxAttempts?: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
61
68
|
export interface ReleasedRegistrySlot {
|
|
62
69
|
serviceValue: string;
|
|
63
70
|
serviceId: string;
|
|
@@ -71,6 +78,13 @@ export interface ReleaseSystemRegistrySlotsOutcome {
|
|
|
71
78
|
unchangedServiceValues: string[];
|
|
72
79
|
}
|
|
73
80
|
|
|
81
|
+
export interface ReleaseSystemRegistrySlotsByServiceIdOutcome {
|
|
82
|
+
config: Config;
|
|
83
|
+
released: ReleasedRegistrySlot[];
|
|
84
|
+
/** Requested `serviceIds` with no ACTIVE slot released (unknown id, already EMPTY, or never bound). */
|
|
85
|
+
unchangedServiceIds: string[];
|
|
86
|
+
}
|
|
87
|
+
|
|
74
88
|
export interface AppendSystemRegistrySlotsInput {
|
|
75
89
|
/** Logical service keys to declare with one new EMPTY slot each when missing. */
|
|
76
90
|
serviceValues: string[];
|
|
@@ -365,6 +379,34 @@ function releaseActiveSlotsForServiceValues(
|
|
|
365
379
|
return { nextSlots, released };
|
|
366
380
|
}
|
|
367
381
|
|
|
382
|
+
function releaseActiveSlotsForServiceIds(
|
|
383
|
+
slots: ServiceSlot[],
|
|
384
|
+
serviceIdSet: ReadonlySet<string>,
|
|
385
|
+
): { nextSlots: ServiceSlot[]; released: ReleasedRegistrySlot[] } {
|
|
386
|
+
const nextSlots = [...slots];
|
|
387
|
+
const released: ReleasedRegistrySlot[] = [];
|
|
388
|
+
|
|
389
|
+
for (let slotIndex = 0; slotIndex < nextSlots.length; slotIndex += 1) {
|
|
390
|
+
const slot = nextSlots[slotIndex];
|
|
391
|
+
if (slot.serviceId == null || !serviceIdSet.has(slot.serviceId) || slot.status !== ServiceSlotStatus.ACTIVE) {
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
released.push({
|
|
396
|
+
serviceValue: slot.serviceValue,
|
|
397
|
+
serviceId: slot.serviceId,
|
|
398
|
+
slotIndex,
|
|
399
|
+
});
|
|
400
|
+
nextSlots[slotIndex] = {
|
|
401
|
+
...slot,
|
|
402
|
+
serviceId: null,
|
|
403
|
+
status: ServiceSlotStatus.EMPTY,
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return { nextSlots, released };
|
|
408
|
+
}
|
|
409
|
+
|
|
368
410
|
/**
|
|
369
411
|
* Force-release ACTIVE registry slots for the given logical service keys (`ACTIVE → EMPTY`).
|
|
370
412
|
* Ops/dev recovery when a process crashed without {@link unregisterService}.
|
|
@@ -475,6 +517,106 @@ export async function releaseSystemRegistrySlots(
|
|
|
475
517
|
);
|
|
476
518
|
}
|
|
477
519
|
|
|
520
|
+
/**
|
|
521
|
+
* Force-release ACTIVE registry slots for the given runtime Service row ids (`ACTIVE → EMPTY`).
|
|
522
|
+
* Targets one slot per `serviceId` — use when multiple slots share the same `serviceValue`.
|
|
523
|
+
* Ops/dev recovery when a process crashed without {@link unregisterService}.
|
|
524
|
+
* Does not delete Service rows or mutate `details.runtime`.
|
|
525
|
+
*/
|
|
526
|
+
export async function releaseSystemRegistrySlotsByServiceId(
|
|
527
|
+
input: ReleaseSystemRegistrySlotsByServiceIdInput,
|
|
528
|
+
): Promise<ReleaseSystemRegistrySlotsByServiceIdOutcome> {
|
|
529
|
+
const serviceIds = [...new Set(input.serviceIds.map((value) => value.trim()).filter((value) => value !== ""))];
|
|
530
|
+
if (serviceIds.length === 0) {
|
|
531
|
+
throw new Error("[releaseSystemRegistrySlotsByServiceId] serviceIds must not be empty");
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
const serviceIdSet = new Set(serviceIds);
|
|
535
|
+
const maxAttempts = input.maxAttempts ?? DEFAULT_REGISTER_RETRY_ATTEMPTS;
|
|
536
|
+
const logger = createLogger({
|
|
537
|
+
module: "releaseSystemRegistrySlotsByServiceId",
|
|
538
|
+
traceId: input.traceId,
|
|
539
|
+
labels: { serviceIds: serviceIds.join(",") },
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
logger.info("开始按 serviceId 强制释放 registry 槽位", {
|
|
543
|
+
topic: LOG_TOPIC_REGISTRY,
|
|
544
|
+
data: { serviceIds },
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
548
|
+
try {
|
|
549
|
+
const config = await loadSystemRegistryConfig();
|
|
550
|
+
const revision = parseRegistryRevision(config.details.meta);
|
|
551
|
+
const slots = parseServiceSlots(config);
|
|
552
|
+
|
|
553
|
+
const { nextSlots, released } = releaseActiveSlotsForServiceIds(slots, serviceIdSet);
|
|
554
|
+
const releasedIdSet = new Set(released.map((entry) => entry.serviceId));
|
|
555
|
+
const unchangedServiceIds = serviceIds.filter((serviceId) => !releasedIdSet.has(serviceId));
|
|
556
|
+
|
|
557
|
+
if (released.length === 0) {
|
|
558
|
+
logger.info("无 ACTIVE 槽位需要释放", {
|
|
559
|
+
topic: LOG_TOPIC_REGISTRY,
|
|
560
|
+
data: { serviceIds, attempt },
|
|
561
|
+
});
|
|
562
|
+
return { config, released, unchangedServiceIds: serviceIds };
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
await persistSlotClaim({
|
|
566
|
+
configId: config.id,
|
|
567
|
+
revision,
|
|
568
|
+
slots: nextSlots,
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
const updated = await loadSystemRegistryConfig();
|
|
572
|
+
logger.info("槽位强制释放成功", {
|
|
573
|
+
topic: LOG_TOPIC_REGISTRY,
|
|
574
|
+
data: {
|
|
575
|
+
released,
|
|
576
|
+
unchangedServiceIds,
|
|
577
|
+
attempt,
|
|
578
|
+
revision: revision + 1,
|
|
579
|
+
},
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
return {
|
|
583
|
+
config: updated,
|
|
584
|
+
released,
|
|
585
|
+
unchangedServiceIds,
|
|
586
|
+
};
|
|
587
|
+
} catch (error) {
|
|
588
|
+
if (error instanceof ServiceRegistryError) {
|
|
589
|
+
logger.error("槽位强制释放被拒绝", {
|
|
590
|
+
topic: LOG_TOPIC_REGISTRY,
|
|
591
|
+
data: { serviceIds, code: error.code, message: error.message },
|
|
592
|
+
});
|
|
593
|
+
throw error;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
if (isOptimisticLockError(error) && attempt < maxAttempts) {
|
|
597
|
+
logger.warn("registry 乐观锁冲突,重试", {
|
|
598
|
+
topic: LOG_TOPIC_REGISTRY,
|
|
599
|
+
data: { serviceIds, attempt, maxAttempts },
|
|
600
|
+
});
|
|
601
|
+
await sleep(50 * attempt);
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
606
|
+
logger.error("槽位强制释放失败", {
|
|
607
|
+
topic: LOG_TOPIC_REGISTRY,
|
|
608
|
+
data: { serviceIds, attempt, message },
|
|
609
|
+
});
|
|
610
|
+
throw new ServiceRegistryError(message, "REGISTRY_UPDATE_FAILED");
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
throw new ServiceRegistryError(
|
|
615
|
+
"[releaseSystemRegistrySlotsByServiceId] Optimistic lock retries exhausted",
|
|
616
|
+
"REGISTRY_UPDATE_FAILED",
|
|
617
|
+
);
|
|
618
|
+
}
|
|
619
|
+
|
|
478
620
|
/**
|
|
479
621
|
* Append EMPTY {@link ServiceSlot} rows for logical service keys not yet declared.
|
|
480
622
|
* Idempotent — skips keys that already appear in `details.objects`.
|