forked from THU-MAIC/OpenMAIC
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstrumentation.ts
More file actions
99 lines (94 loc) · 4.27 KB
/
Copy pathinstrumentation.ts
File metadata and controls
99 lines (94 loc) · 4.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/**
* Process-scoped startup work.
*
* Next calls `register` once per server instance, before it serves a request.
* That makes it the only place in this app where a background schedule can
* live: a route module has no such guarantee — it can be instantiated more than
* once and gets no shutdown hook — so anything periodic started from one is
* really started per instantiation.
*
* `register` must return before the server is ready, so nothing here may block
* on I/O. Starting a timer does not.
*/
export async function register(): Promise<void> {
// Also invoked for the Edge runtime, which has neither `pg` nor timers we
// want; the persistence stack is Node-only.
if (process.env.NEXT_RUNTIME !== 'nodejs') return;
// Imported dynamically so the Edge bundle never pulls in `pg`.
const { startAssetCollectorSchedule } =
await import('@/lib/persistence/asset-collector-schedule');
const assetSchedule = startAssetCollectorSchedule();
// Warn-first boot-time validation of model routing config (MODEL_ROUTES,
// DEFAULT_MODEL, <PREFIX>_MODELS). Cheap and non-throwing: broken config
// surfaces here as [config] warnings instead of failing at request time.
// Imported dynamically so the Edge bundle never pulls in the fs/js-yaml
// backed provider config it reads.
const { validateServerConfig } = await import('@/lib/server/config-validation');
validateServerConfig();
let runner: import('@/lib/server/agent-runtime/runner').AgentRunnerHandle | undefined;
let extractionRunner:
| import('@/lib/server/material-extraction/runner').MaterialExtractionRunnerHandle
| undefined;
let stopAgentEventNotifyBus: (() => Promise<void>) | null = null;
try {
const { isAgentRuntimeConfigured } = await import('@/lib/config/feature-flags');
if (isAgentRuntimeConfigured()) {
// One dedicated LISTEN connection per application instance. The HTTP
// SSE routes and the runner share its in-process fanout registry; it is
// not a pool client and never scales with the number of streams.
const { startAgentEventNotifyBus } =
await import('@/lib/server/agent-runtime/event-notify-bus');
const eventNotifyBus = startAgentEventNotifyBus();
stopAgentEventNotifyBus = () => eventNotifyBus.stop();
// startAgentRunner only installs a timer. Store/schema initialization is
// retained behind the store's lazy promise and never blocks register().
const runtime = await import('@/lib/server/agent-runtime/runner');
runner = runtime.startAgentRunner();
const extraction = await import('@/lib/server/material-extraction/runner');
extractionRunner = extraction.startMaterialExtractionRunner();
}
} catch (error) {
console.error('[instrumentation] Agent runtime startup failed', error);
}
let shutdownPromise: Promise<void> | undefined;
const shutdown = (): Promise<void> => {
shutdownPromise ??= (async () => {
// Park sessions before any pool they use is closed. This preserves the
// last durable entry-tree checkpoint for immediate takeover.
try {
await extractionRunner?.stop();
} catch (error) {
console.error('[instrumentation] Material extraction runner drain failed', error);
}
try {
await runner?.stop();
} catch (error) {
console.error('[instrumentation] Agent runner drain failed', error);
}
try {
await stopAgentEventNotifyBus?.();
} catch (error) {
console.error('[instrumentation] Agent event notify bus drain failed', error);
}
try {
await assetSchedule?.stop();
} catch (error) {
console.error('[instrumentation] Asset collector drain failed', error);
}
const connectionString = process.env.DATABASE_URL?.trim();
if (connectionString) {
try {
const { getServerPersistenceProvider } =
await import('@/lib/persistence/server-provider');
const { pool } = await getServerPersistenceProvider(connectionString);
await pool.end();
} catch (error) {
console.error('[instrumentation] Persistence pool shutdown failed', error);
}
}
})();
return shutdownPromise;
};
process.once('SIGTERM', () => void shutdown());
process.once('SIGINT', () => void shutdown());
}