poe-code 14.0.0 → 14.0.1
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/index.js +97 -46
- package/dist/index.js.map +3 -3
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/process-launcher/dist/launcher.js +90 -45
package/package.json
CHANGED
|
@@ -16,8 +16,11 @@ const TEMP_WRITE_MAX_ATTEMPTS = 3;
|
|
|
16
16
|
export async function startManagedProcess(options) {
|
|
17
17
|
assertOptionalFiniteDuration(options.startupTimeoutMs, "startup timeout");
|
|
18
18
|
assertOptionalFiniteDuration(options.pollIntervalMs, "poll interval");
|
|
19
|
-
const fs = options.fs ?? defaultFs();
|
|
20
19
|
const spec = normalizeSpec(options.spec);
|
|
20
|
+
return await withManagedProcessOperation({ ...options, id: spec.id }, async (fs) => await startReservedProcess({ ...options, fs, spec }));
|
|
21
|
+
}
|
|
22
|
+
async function startReservedProcess(options) {
|
|
23
|
+
const { fs, spec } = options;
|
|
21
24
|
const existing = await readManagedProcess({
|
|
22
25
|
baseDir: options.baseDir,
|
|
23
26
|
fs,
|
|
@@ -60,7 +63,10 @@ export async function startManagedProcess(options) {
|
|
|
60
63
|
export async function stopManagedProcess(options) {
|
|
61
64
|
assertOptionalFiniteDuration(options.stopTimeoutMs, "stop timeout");
|
|
62
65
|
assertOptionalFiniteDuration(options.pollIntervalMs, "poll interval");
|
|
63
|
-
|
|
66
|
+
return await withManagedProcessOperation(options, async (fs) => await stopReservedProcess({ ...options, fs }));
|
|
67
|
+
}
|
|
68
|
+
async function stopReservedProcess(options) {
|
|
69
|
+
const { fs } = options;
|
|
64
70
|
const record = await readManagedProcess({
|
|
65
71
|
baseDir: options.baseDir,
|
|
66
72
|
fs,
|
|
@@ -106,37 +112,75 @@ export async function stopManagedProcess(options) {
|
|
|
106
112
|
return stopped;
|
|
107
113
|
}
|
|
108
114
|
export async function restartManagedProcess(options) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
+
assertOptionalFiniteDuration(options.startupTimeoutMs, "startup timeout");
|
|
116
|
+
assertOptionalFiniteDuration(options.stopTimeoutMs, "stop timeout");
|
|
117
|
+
assertOptionalFiniteDuration(options.pollIntervalMs, "poll interval");
|
|
118
|
+
return await withManagedProcessOperation(options, async (fs) => {
|
|
119
|
+
const record = await readManagedProcess({
|
|
120
|
+
baseDir: options.baseDir,
|
|
121
|
+
fs,
|
|
122
|
+
id: options.id,
|
|
123
|
+
isPidRunning: options.isPidRunning
|
|
124
|
+
});
|
|
125
|
+
if (record.spec === null) {
|
|
126
|
+
throw await managedProcessNotFound(fs, options.baseDir, options.id);
|
|
127
|
+
}
|
|
128
|
+
await stopReservedProcess({
|
|
129
|
+
...options,
|
|
130
|
+
force: false,
|
|
131
|
+
fs
|
|
132
|
+
});
|
|
133
|
+
return await startReservedProcess({
|
|
134
|
+
...options,
|
|
135
|
+
fs,
|
|
136
|
+
spec: normalizeSpec(record.spec)
|
|
137
|
+
});
|
|
115
138
|
});
|
|
116
|
-
|
|
117
|
-
|
|
139
|
+
}
|
|
140
|
+
async function withManagedProcessOperation(options, operation) {
|
|
141
|
+
const fs = options.fs ?? defaultFs();
|
|
142
|
+
await assertProcessDirectorySafe(fs, options.baseDir, options.id);
|
|
143
|
+
await fs.mkdir(options.baseDir, { recursive: true });
|
|
144
|
+
const baseDir = path.resolve(options.baseDir);
|
|
145
|
+
const operationsDir = path.join(path.dirname(baseDir), ".process-operations", path.basename(baseDir));
|
|
146
|
+
await assertPathHasNoSymbolicLinks(fs, operationsDir);
|
|
147
|
+
await fs.mkdir(operationsDir, { recursive: true });
|
|
148
|
+
const lockPath = path.join(operationsDir, options.id);
|
|
149
|
+
const owner = `${JSON.stringify({ token: randomUUID(), pid: process.pid })}\n`;
|
|
150
|
+
try {
|
|
151
|
+
await fs.writeFile(lockPath, owner, { encoding: "utf8", flag: "wx" });
|
|
118
152
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
153
|
+
catch (error) {
|
|
154
|
+
if (hasOwnErrorCode(error, "EEXIST")) {
|
|
155
|
+
throw new UserError(`Managed process "${options.id}" has another operation in progress.\n` +
|
|
156
|
+
"Retry after it finishes.\n" +
|
|
157
|
+
"If the caller exited unexpectedly, confirm that all operations on this name have stopped,\n" +
|
|
158
|
+
`then remove this reservation file:\n${lockPath}`);
|
|
159
|
+
}
|
|
160
|
+
throw error;
|
|
161
|
+
}
|
|
162
|
+
let outcome;
|
|
163
|
+
try {
|
|
164
|
+
outcome = { result: await operation(fs) };
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
outcome = { error };
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
if (await fs.readFile(lockPath, "utf8") !== owner) {
|
|
171
|
+
throw new UserError(`Managed process operation ownership changed before release: ${lockPath}`);
|
|
172
|
+
}
|
|
173
|
+
await fs.rm(lockPath);
|
|
174
|
+
}
|
|
175
|
+
catch (releaseError) {
|
|
176
|
+
if ("error" in outcome) {
|
|
177
|
+
throw new AggregateError([outcome.error, releaseError], "Managed process operation and ownership release failed");
|
|
178
|
+
}
|
|
179
|
+
throw releaseError;
|
|
180
|
+
}
|
|
181
|
+
if ("error" in outcome)
|
|
182
|
+
throw outcome.error;
|
|
183
|
+
return outcome.result;
|
|
140
184
|
}
|
|
141
185
|
async function describeStartFailure(fs, baseDir, id, record) {
|
|
142
186
|
const state = record.state;
|
|
@@ -339,21 +383,22 @@ function getFileId(stat) {
|
|
|
339
383
|
: null;
|
|
340
384
|
}
|
|
341
385
|
export async function removeManagedProcess(options) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
386
|
+
await withManagedProcessOperation(options, async (fs) => {
|
|
387
|
+
const record = await readManagedProcess({
|
|
388
|
+
baseDir: options.baseDir,
|
|
389
|
+
fs,
|
|
390
|
+
id: options.id,
|
|
391
|
+
isPidRunning: options.isPidRunning
|
|
392
|
+
});
|
|
393
|
+
if (isActiveRecord(record)) {
|
|
394
|
+
throw new Error(`Managed process "${options.id}" must be stopped before removal.`);
|
|
395
|
+
}
|
|
396
|
+
const stateStore = createStateStore(options.baseDir, fs);
|
|
397
|
+
await stateStore.remove(options.id);
|
|
398
|
+
if (record.spec !== null && options.removeRuntimeArtifacts) {
|
|
399
|
+
await options.removeRuntimeArtifacts({ record });
|
|
400
|
+
}
|
|
348
401
|
});
|
|
349
|
-
if (isActiveRecord(record)) {
|
|
350
|
-
throw new Error(`Managed process "${options.id}" must be stopped before removal.`);
|
|
351
|
-
}
|
|
352
|
-
const stateStore = createStateStore(options.baseDir, fs);
|
|
353
|
-
await stateStore.remove(options.id);
|
|
354
|
-
if (record.spec !== null && options.removeRuntimeArtifacts) {
|
|
355
|
-
await options.removeRuntimeArtifacts({ record });
|
|
356
|
-
}
|
|
357
402
|
}
|
|
358
403
|
export async function runManagedProcess(options) {
|
|
359
404
|
if (options.signal?.aborted) {
|