bunqueue-dashboard 0.0.34 → 0.0.36
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/README.md +20 -13
- package/agent/backup/processExecutor.ts +90 -0
- package/agent/backup/resultValidation.ts +85 -0
- package/agent/backup/routes.ts +160 -0
- package/agent/backup/runner.ts +91 -0
- package/agent/backup/standaloneWorker.ts +23 -0
- package/agent/backup/workerExecutor.ts +40 -0
- package/agent/backup/workerFactory.ts +21 -0
- package/agent/backup/workerProtocol.ts +10 -0
- package/agent/db/core.ts +141 -0
- package/agent/db/csvExport.ts +172 -0
- package/agent/db/exportTimeout.ts +190 -0
- package/agent/db/query.ts +82 -0
- package/agent/db/queryTimeout.ts +76 -0
- package/agent/db/schema.ts +79 -0
- package/agent/db/tables.ts +157 -0
- package/agent/db/types.ts +118 -0
- package/agent/db/workerFactory.ts +25 -0
- package/agent/db.ts +43 -1099
- package/agent/errorMessage.ts +9 -0
- package/agent/flow/routes.ts +250 -0
- package/agent/flow/service.ts +266 -0
- package/agent/flow/types.ts +34 -0
- package/agent/flow/validation.ts +230 -0
- package/agent/index.ts +5 -17
- package/agent/logger.ts +121 -17
- package/agent/managedTarget.ts +43 -0
- package/agent/manager/config.ts +84 -0
- package/agent/manager/logs.ts +83 -0
- package/agent/manager/process.ts +233 -0
- package/agent/manager/storage.ts +28 -0
- package/agent/manager/types.ts +38 -0
- package/agent/manager.ts +10 -490
- package/agent/queue/routes.ts +128 -0
- package/agent/queue/runtime.ts +119 -0
- package/agent/queue/types.ts +34 -0
- package/agent/queue/validation.ts +100 -0
- package/agent/server/controlRoutes.ts +153 -0
- package/agent/server/databaseRoutes.ts +165 -0
- package/agent/server/errors.ts +48 -0
- package/agent/server/handler.ts +146 -0
- package/agent/server/jsonBody.ts +109 -0
- package/agent/server/lifecycle.ts +72 -0
- package/agent/server/managedRuntime.ts +41 -0
- package/agent/server/policy.ts +60 -0
- package/agent/server/router.ts +150 -0
- package/agent/server/types.ts +39 -0
- package/agent/server/workflowReadRoutes.ts +80 -0
- package/agent/server.ts +16 -369
- package/agent/shutdown.ts +156 -0
- package/agent/workflow/codec.ts +78 -0
- package/agent/workflow/detail.ts +63 -0
- package/agent/workflow/list.ts +87 -0
- package/agent/workflow/runtime.ts +274 -0
- package/agent/workflow/runtimeConfig.ts +103 -0
- package/agent/workflow/runtimeRoutes.ts +162 -0
- package/agent/workflow/sqlite.ts +52 -0
- package/agent/workflow/stats.ts +79 -0
- package/agent/workflow/types.ts +81 -0
- package/agent/workflow/validation.ts +114 -0
- package/agent/workflows.ts +16 -0
- package/dist/.vite/manifest.json +619 -246
- package/dist/assets/AddJob-UUa2fSXE.js +3 -0
- package/dist/assets/Alerts-7oGYfQMb.js +1 -0
- package/dist/assets/{AreaChart-REK4ZsTC.js → AreaChart-w0ruozXH.js} +1 -1
- package/dist/assets/Benchmark-C2NFp_kj.js +1 -0
- package/dist/assets/BulkAddJobs-CL4yBae-.js +5 -0
- package/dist/assets/Button-BPqpRZJD.js +1 -0
- package/dist/assets/Card-C7NMhqUt.js +1 -0
- package/dist/assets/{CopilotPanel-CIXpcwkH.js → CopilotPanel-BQ2Cgo9p.js} +3 -3
- package/dist/assets/Cron-DfWBhoBf.js +1 -0
- package/dist/assets/CronManager-DAK7RSOX.js +1 -0
- package/dist/assets/Database-DqL7giEj.js +3 -0
- package/dist/assets/Diagnostics-D98YwN-6.js +1 -0
- package/dist/assets/Dlq-BHmA5PTI.js +1 -0
- package/dist/assets/DlqControl-DihxvP-i.js +1 -0
- package/dist/assets/DlqPro-ncgnDtpE.js +1 -0
- package/dist/assets/Flows-B5N5Cil0.js +2 -0
- package/dist/assets/JobInspector-B40nFiGh.js +2 -0
- package/dist/assets/Jobs-Bla3IEef.js +1 -0
- package/dist/assets/JobsPro-CnczVx7x.js +1 -0
- package/dist/assets/Logs-T91Q3cH0.js +1 -0
- package/dist/assets/LogsPro-CMn6-Wwv.js +1 -0
- package/dist/assets/{McpServer-D5rwBg74.js → McpServer-BQBabwW-.js} +2 -2
- package/dist/assets/Metrics-DxT_RI2B.js +1 -0
- package/dist/assets/MetricsPro-Cjen-nAP.js +1 -0
- package/dist/assets/Overview-XN2ej8ph.js +1 -0
- package/dist/assets/PageHeader-BXlZSBcc.js +1 -0
- package/dist/assets/Pagination-Q-vf4hsX.js +1 -0
- package/dist/assets/QueueActions-C-Aferd6.js +1 -0
- package/dist/assets/QueueControl-B8Q9NX6t.js +1 -0
- package/dist/assets/QueueDetail-BMhG0jUB.js +1 -0
- package/dist/assets/QueueDetailPro-BKTTyLR4.js +1 -0
- package/dist/assets/Queues-COqPMoY9.js +1 -0
- package/dist/assets/QueuesOverview-pWdrPy8Z.js +1 -0
- package/dist/assets/S3Backup-BmsZ8xtq.js +1 -0
- package/dist/assets/S3BackupPro-AtlsPUJL.js +3 -0
- package/dist/assets/ServerControl-D3XwHr72.js +3 -0
- package/dist/assets/Settings-BofKZoHn.js +1 -0
- package/dist/assets/StatusBadge-B0I7hNBX.js +1 -0
- package/dist/assets/Usage-DAR9E22v.js +1 -0
- package/dist/assets/UsagePro-Bc30N2Lo.js +1 -0
- package/dist/assets/Webhooks-Bg2k1PU4.js +1 -0
- package/dist/assets/Workers-BqUZMJVQ.js +1 -0
- package/dist/assets/WorkersPro-C9aSadUh.js +1 -0
- package/dist/assets/Workflows-BEFMfHmo.js +1 -0
- package/dist/assets/api-CQ5Z7xR7.js +1 -0
- package/dist/assets/bq-BeBxa743.js +1 -0
- package/dist/assets/cn-zFEt5SO8.js +1 -0
- package/dist/assets/connectionStore-DbBYqHEY.js +1 -0
- package/dist/assets/controlConnectionEpoch-CFSO6237.js +1 -0
- package/dist/assets/feedback-BnGE2oW2.js +1 -0
- package/dist/assets/{flowMutationSafety-DVD1IMr-.js → flowMutationSafety-CoOp94wS.js} +1 -1
- package/dist/assets/{form-DsUq0w8s.js → form-tC20r4Ma.js} +1 -1
- package/dist/assets/format-Cg7VCIZW.js +1 -0
- package/dist/assets/icons-CIvFfU2b.js +1 -0
- package/dist/assets/index-Cui9IwWy.js +8 -0
- package/dist/assets/index-DOze4TKg.css +1 -0
- package/dist/assets/install-Cd9Is10G.js +3 -0
- package/dist/assets/{react-vendor-Bjui4wS4.js → react-vendor-CyjgmGTq.js} +3 -3
- package/dist/assets/responses-kPO4rSu5.js +1 -0
- package/dist/assets/toastStore-CS_9Xndn.js +1 -0
- package/dist/assets/{upstreamPaths-nG8N1XAz.js → upstreamPaths-D_LPsv7b.js} +1 -1
- package/dist/assets/usePolledData-DzlUpBOO.js +1 -0
- package/dist/assets/{useServerActionGuard-CItj3hvh.js → useServerActionGuard-BlH-Kso1.js} +1 -1
- package/dist/assets/useThroughputSeries-C2pa1Wd_.js +1 -0
- package/dist/index.html +17 -6
- package/package.json +15 -3
- package/scripts/embedded.gen.ts +152 -124
- package/scripts/serve.ts +96 -484
- package/scripts/serveHandler.ts +217 -0
- package/scripts/servePolicy.ts +133 -0
- package/dist/assets/AddJob-Cih9F84t.js +0 -3
- package/dist/assets/Alerts-Dp4Vclez.js +0 -1
- package/dist/assets/Benchmark-X_gdZun5.js +0 -1
- package/dist/assets/BulkAddJobs-CXTpYMZf.js +0 -5
- package/dist/assets/Cron-DUHkse77.js +0 -1
- package/dist/assets/CronManager-BeYrLK2E.js +0 -1
- package/dist/assets/Database-CXPb3XGr.js +0 -3
- package/dist/assets/Diagnostics-DDtoiDYT.js +0 -1
- package/dist/assets/Dlq-CX_uRblW.js +0 -1
- package/dist/assets/DlqControl-CazFmSEd.js +0 -1
- package/dist/assets/DlqPro-HSffdtLJ.js +0 -1
- package/dist/assets/Flows-CGmyghKF.js +0 -1
- package/dist/assets/JobInspector-B9i1HnG5.js +0 -2
- package/dist/assets/Jobs-BZGtMnJI.js +0 -1
- package/dist/assets/JobsPro-tmEN8f-P.js +0 -1
- package/dist/assets/Logs-DxUD9V2A.js +0 -1
- package/dist/assets/LogsPro-BTQhvPKj.js +0 -1
- package/dist/assets/Metrics-CSPpBf1m.js +0 -1
- package/dist/assets/MetricsPro-DSn-3qNT.js +0 -1
- package/dist/assets/Overview-StvHYRZ5.js +0 -1
- package/dist/assets/Pagination-eotgGQf9.js +0 -1
- package/dist/assets/QueueActions-CibRLzrz.js +0 -1
- package/dist/assets/QueueControl-DwYNcMfI.js +0 -1
- package/dist/assets/QueueDetail-NMfKwj6E.js +0 -1
- package/dist/assets/QueueDetailPro-C8SBjX09.js +0 -1
- package/dist/assets/Queues-BeTAi8V8.js +0 -1
- package/dist/assets/QueuesOverview-BfQO8NS4.js +0 -1
- package/dist/assets/S3Backup-BYkAtONl.js +0 -1
- package/dist/assets/S3BackupPro-BP1Ch54R.js +0 -2
- package/dist/assets/ServerControl-C85jYgyN.js +0 -3
- package/dist/assets/Settings-DjP28c_5.js +0 -1
- package/dist/assets/Usage-DECeEsO2.js +0 -1
- package/dist/assets/UsagePro-CD7dgt3d.js +0 -1
- package/dist/assets/Webhooks-Ct-x8DD1.js +0 -1
- package/dist/assets/Workers-lP1BXHFq.js +0 -1
- package/dist/assets/WorkersPro-CAUqy3Cp.js +0 -1
- package/dist/assets/cn-CMFYpumL.js +0 -1
- package/dist/assets/connectionStore-Cd9-3Fw0.js +0 -1
- package/dist/assets/index-BWoUj86M.css +0 -1
- package/dist/assets/index-Dr__4DsT.js +0 -8
- package/dist/assets/install-DPCcfOYo.js +0 -3
- package/dist/assets/useThroughputSeries-Bpyg6Jaq.js +0 -1
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { copyConfig, defaultConfig, validateConfigPatch, validateServerConfig } from './config';
|
|
2
|
+
import { ProcessLogs } from './logs';
|
|
3
|
+
import { databaseStats } from './storage';
|
|
4
|
+
import type {
|
|
5
|
+
DbStats,
|
|
6
|
+
LogLine,
|
|
7
|
+
ServerConfig,
|
|
8
|
+
Status,
|
|
9
|
+
StatusSnapshot,
|
|
10
|
+
} from './types';
|
|
11
|
+
|
|
12
|
+
const STOP_TIMEOUT_MS = 8000;
|
|
13
|
+
type ManagedProcess = ReturnType<typeof Bun.spawn>;
|
|
14
|
+
|
|
15
|
+
async function exitsWithin(process: ManagedProcess, timeout: number): Promise<boolean> {
|
|
16
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
17
|
+
return Promise.race([
|
|
18
|
+
process.exited.then(() => true),
|
|
19
|
+
new Promise<boolean>((resolve) => {
|
|
20
|
+
timer = setTimeout(() => resolve(false), timeout);
|
|
21
|
+
}),
|
|
22
|
+
]).finally(() => clearTimeout(timer));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Supervises one bunqueue server child process. */
|
|
26
|
+
export class ProcessManager {
|
|
27
|
+
private proc: ManagedProcess | null = null;
|
|
28
|
+
private status: Status = 'stopped';
|
|
29
|
+
private startedAt: number | null = null;
|
|
30
|
+
private exitCode: number | null = null;
|
|
31
|
+
private config: ServerConfig = defaultConfig();
|
|
32
|
+
private runningConfig: ServerConfig | null = null;
|
|
33
|
+
private procToken = 0;
|
|
34
|
+
private stopping: Promise<StatusSnapshot> | null = null;
|
|
35
|
+
private shuttingDown = false;
|
|
36
|
+
private maintenance: string | null = null;
|
|
37
|
+
private output = new ProcessLogs();
|
|
38
|
+
|
|
39
|
+
constructor(private readonly stopTimeoutMs = STOP_TIMEOUT_MS) {}
|
|
40
|
+
|
|
41
|
+
getConfig(): ServerConfig {
|
|
42
|
+
return copyConfig(this.config);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setConfig(patch: Partial<ServerConfig>): ServerConfig {
|
|
46
|
+
const valid = validateConfigPatch(patch);
|
|
47
|
+
this.config = {
|
|
48
|
+
...this.config,
|
|
49
|
+
...valid,
|
|
50
|
+
extraEnv: valid.extraEnv ?? this.config.extraEnv,
|
|
51
|
+
};
|
|
52
|
+
return copyConfig(this.config);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
getStatus(): StatusSnapshot {
|
|
56
|
+
return {
|
|
57
|
+
status: this.status,
|
|
58
|
+
generation: this.procToken,
|
|
59
|
+
pid: this.proc?.pid ?? null,
|
|
60
|
+
startedAt: this.startedAt,
|
|
61
|
+
exitCode: this.exitCode,
|
|
62
|
+
config: copyConfig(this.config),
|
|
63
|
+
runningConfig: this.runningConfig ? copyConfig(this.runningConfig) : null,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
dbStats(): Promise<DbStats> {
|
|
68
|
+
return databaseStats(this.config.dataPath);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getLogs(): LogLine[] {
|
|
72
|
+
return this.output.get();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async start(): Promise<StatusSnapshot> {
|
|
76
|
+
this.assertNoMaintenance('start');
|
|
77
|
+
if (this.shuttingDown) return this.getStatus();
|
|
78
|
+
if (this.status === 'running' || this.status === 'starting') return this.getStatus();
|
|
79
|
+
if (this.stopping) await this.stopping;
|
|
80
|
+
this.assertNoMaintenance('start');
|
|
81
|
+
if (this.shuttingDown) return this.getStatus();
|
|
82
|
+
const statusAfterWait = this.status as Status;
|
|
83
|
+
if (statusAfterWait === 'running' || statusAfterWait === 'starting') {
|
|
84
|
+
return this.getStatus();
|
|
85
|
+
}
|
|
86
|
+
if (this.proc) {
|
|
87
|
+
throw new Error(
|
|
88
|
+
`Cannot start while the previous managed process (pid ${this.proc.pid}) is still alive`
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const launchConfig = validateServerConfig(this.config);
|
|
93
|
+
const [command, ...args] = launchConfig.command.trim().split(/\s+/);
|
|
94
|
+
this.status = 'starting';
|
|
95
|
+
this.exitCode = null;
|
|
96
|
+
const token = ++this.procToken;
|
|
97
|
+
const env: Record<string, string> = {
|
|
98
|
+
...(process.env as Record<string, string>),
|
|
99
|
+
...launchConfig.extraEnv,
|
|
100
|
+
HTTP_PORT: String(launchConfig.httpPort),
|
|
101
|
+
TCP_PORT: String(launchConfig.tcpPort),
|
|
102
|
+
BUNQUEUE_DATA_PATH: launchConfig.dataPath,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
this.proc = Bun.spawn([command, ...args], {
|
|
107
|
+
env,
|
|
108
|
+
stdout: 'pipe',
|
|
109
|
+
stderr: 'pipe',
|
|
110
|
+
onExit: (_process, code) => {
|
|
111
|
+
this.output.cancel(token);
|
|
112
|
+
if (this.procToken !== token) return;
|
|
113
|
+
this.exitCode = code ?? null;
|
|
114
|
+
this.status = 'stopped';
|
|
115
|
+
this.proc = null;
|
|
116
|
+
this.runningConfig = null;
|
|
117
|
+
this.output.push('sys', `process exited (code ${code ?? '?'})`);
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
} catch (error) {
|
|
121
|
+
this.status = 'stopped';
|
|
122
|
+
this.proc = null;
|
|
123
|
+
this.runningConfig = null;
|
|
124
|
+
throw new Error(`Failed to spawn "${command}": ${(error as Error).message}`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
this.startedAt = Date.now();
|
|
128
|
+
this.status = 'running';
|
|
129
|
+
this.runningConfig = copyConfig(launchConfig);
|
|
130
|
+
this.output.push('sys', `started: ${launchConfig.command} (pid ${this.proc.pid})`);
|
|
131
|
+
const isCurrent = () => this.procToken === token;
|
|
132
|
+
void this.output.capture(
|
|
133
|
+
this.proc.stdout as unknown as ReadableStream<Uint8Array>,
|
|
134
|
+
'stdout',
|
|
135
|
+
token,
|
|
136
|
+
isCurrent
|
|
137
|
+
);
|
|
138
|
+
void this.output.capture(
|
|
139
|
+
this.proc.stderr as unknown as ReadableStream<Uint8Array>,
|
|
140
|
+
'stderr',
|
|
141
|
+
token,
|
|
142
|
+
isCurrent
|
|
143
|
+
);
|
|
144
|
+
return this.getStatus();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
stop(): Promise<StatusSnapshot> {
|
|
148
|
+
if (this.stopping) return this.stopping;
|
|
149
|
+
const pending = this.stopOnce();
|
|
150
|
+
this.stopping = pending;
|
|
151
|
+
const clearStopping = () => {
|
|
152
|
+
if (this.stopping === pending) this.stopping = null;
|
|
153
|
+
};
|
|
154
|
+
void pending.then(clearStopping, clearStopping);
|
|
155
|
+
return pending;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Permanently prevent this manager from spawning another child process. */
|
|
159
|
+
beginShutdown(): void {
|
|
160
|
+
this.shuttingDown = true;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Last-resort terminal path used after graceful shutdown times out. */
|
|
164
|
+
forceShutdown(): void {
|
|
165
|
+
this.beginShutdown();
|
|
166
|
+
if (!this.proc) return;
|
|
167
|
+
this.output.push('sys', `force stopping pid ${this.proc.pid} (SIGKILL)`);
|
|
168
|
+
this.proc.kill(9);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async shutdown(): Promise<StatusSnapshot> {
|
|
172
|
+
this.beginShutdown();
|
|
173
|
+
return this.stop();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private async stopOnce(): Promise<StatusSnapshot> {
|
|
177
|
+
if (!this.proc) {
|
|
178
|
+
this.status = 'stopped';
|
|
179
|
+
this.runningConfig = null;
|
|
180
|
+
return this.getStatus();
|
|
181
|
+
}
|
|
182
|
+
this.status = 'stopping';
|
|
183
|
+
this.output.push('sys', 'stopping (SIGTERM)…');
|
|
184
|
+
const process = this.proc;
|
|
185
|
+
const token = this.procToken;
|
|
186
|
+
process.kill();
|
|
187
|
+
if (!(await exitsWithin(process, this.stopTimeoutMs))) {
|
|
188
|
+
this.output.push('sys', 'SIGTERM timed out, sending SIGKILL');
|
|
189
|
+
process.kill(9);
|
|
190
|
+
if (!(await exitsWithin(process, this.stopTimeoutMs))) {
|
|
191
|
+
const message = `pid ${process.pid} did not exit after SIGKILL`;
|
|
192
|
+
this.output.push('sys', `${message} — retaining failed-process tracking`);
|
|
193
|
+
throw new Error(message);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
this.output.cancel(token);
|
|
197
|
+
if (this.procToken !== token) return this.getStatus();
|
|
198
|
+
this.status = 'stopped';
|
|
199
|
+
this.proc = null;
|
|
200
|
+
this.runningConfig = null;
|
|
201
|
+
return this.getStatus();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async restart(): Promise<StatusSnapshot> {
|
|
205
|
+
this.assertNoMaintenance('restart');
|
|
206
|
+
await this.stop();
|
|
207
|
+
return this.start();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** Hold an atomic stopped-server lease across a destructive maintenance task. */
|
|
211
|
+
async withStoppedMaintenance<T>(label: string, operation: () => Promise<T>): Promise<T> {
|
|
212
|
+
if (this.maintenance) {
|
|
213
|
+
throw new Error(`Another maintenance operation is already running: ${this.maintenance}`);
|
|
214
|
+
}
|
|
215
|
+
if (this.proc || this.status !== 'stopped' || this.stopping) {
|
|
216
|
+
throw new Error(`Stop the managed Bunqueue server before ${label}`);
|
|
217
|
+
}
|
|
218
|
+
this.maintenance = label;
|
|
219
|
+
try {
|
|
220
|
+
return await operation();
|
|
221
|
+
} finally {
|
|
222
|
+
if (this.maintenance === label) this.maintenance = null;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private assertNoMaintenance(action: 'start' | 'restart'): void {
|
|
227
|
+
if (this.maintenance) {
|
|
228
|
+
throw new Error(
|
|
229
|
+
`Cannot ${action} the managed Bunqueue server while ${this.maintenance} is running`
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { DbStats } from './types';
|
|
2
|
+
|
|
3
|
+
/** Stat a SQLite database plus its WAL/SHM sidecars. */
|
|
4
|
+
export async function databaseStats(path: string): Promise<DbStats> {
|
|
5
|
+
const one = async (file: string): Promise<{ size: number; mtimeMs: number | null }> => {
|
|
6
|
+
try {
|
|
7
|
+
const handle = Bun.file(file);
|
|
8
|
+
if (!(await handle.exists())) return { size: 0, mtimeMs: null };
|
|
9
|
+
return { size: handle.size, mtimeMs: handle.lastModified };
|
|
10
|
+
} catch {
|
|
11
|
+
return { size: 0, mtimeMs: null };
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const [main, wal, shm] = await Promise.all([
|
|
15
|
+
one(path),
|
|
16
|
+
one(`${path}-wal`),
|
|
17
|
+
one(`${path}-shm`),
|
|
18
|
+
]);
|
|
19
|
+
return {
|
|
20
|
+
path,
|
|
21
|
+
exists: main.mtimeMs !== null,
|
|
22
|
+
size: main.size,
|
|
23
|
+
walSize: wal.size,
|
|
24
|
+
shmSize: shm.size,
|
|
25
|
+
totalSize: main.size + wal.size + shm.size,
|
|
26
|
+
mtimeMs: main.mtimeMs,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export type Status = 'running' | 'stopped' | 'starting' | 'stopping';
|
|
2
|
+
|
|
3
|
+
export interface ServerConfig {
|
|
4
|
+
/** Command to launch the server. */
|
|
5
|
+
command: string;
|
|
6
|
+
httpPort: number;
|
|
7
|
+
tcpPort: number;
|
|
8
|
+
dataPath: string;
|
|
9
|
+
extraEnv: Record<string, string>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface LogLine {
|
|
13
|
+
seq: number;
|
|
14
|
+
ts: number;
|
|
15
|
+
stream: 'stdout' | 'stderr' | 'sys';
|
|
16
|
+
line: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface DbStats {
|
|
20
|
+
path: string;
|
|
21
|
+
exists: boolean;
|
|
22
|
+
size: number;
|
|
23
|
+
walSize: number;
|
|
24
|
+
shmSize: number;
|
|
25
|
+
totalSize: number;
|
|
26
|
+
mtimeMs: number | null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface StatusSnapshot {
|
|
30
|
+
status: Status;
|
|
31
|
+
/** Monotonic identity of the managed process generation. */
|
|
32
|
+
generation: number;
|
|
33
|
+
pid: number | null;
|
|
34
|
+
startedAt: number | null;
|
|
35
|
+
exitCode: number | null;
|
|
36
|
+
config: ServerConfig;
|
|
37
|
+
runningConfig: ServerConfig | null;
|
|
38
|
+
}
|