plum-e2e 2.6.1 → 2.6.2
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.
|
@@ -88,6 +88,17 @@ async function deleteRunner(id) {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Stops/restarts a runner over the network via the primary's control routes,
|
|
93
|
+
* which hit the runner's own /api/shutdown|restart endpoints — works for any
|
|
94
|
+
* reachable runner, not just ones whose process this manager owns by PID.
|
|
95
|
+
*/
|
|
96
|
+
async function controlRunner(id, action) {
|
|
97
|
+
const res = await fetch(`${API_URL}/runners/${id}/${action}`, { method: 'POST' });
|
|
98
|
+
const body = await res.json().catch(() => ({}));
|
|
99
|
+
if (!res.ok || body.ok === false) throw new Error(body.error || `HTTP ${res.status}`);
|
|
100
|
+
}
|
|
101
|
+
|
|
91
102
|
/**
|
|
92
103
|
* Resolves the display + control state for every runner: reachability (ping),
|
|
93
104
|
* whether we own a live process for it, and whether we can control it at all.
|
|
@@ -156,12 +167,8 @@ function prepareNodeEnv() {
|
|
|
156
167
|
async function runAction(r) {
|
|
157
168
|
const options = [];
|
|
158
169
|
|
|
159
|
-
if (
|
|
160
|
-
|
|
161
|
-
pc.dim(`"${r.name}" runs on another machine — it can be pinged but not controlled here.`)
|
|
162
|
-
);
|
|
163
|
-
options.push({ value: 'ping', label: 'Ping' });
|
|
164
|
-
} else if (r.managed) {
|
|
170
|
+
if (r.managed) {
|
|
171
|
+
// Local, and this manager owns its process — control it directly by PID.
|
|
165
172
|
options.push(
|
|
166
173
|
{ value: 'stop', label: pc.red('Stop') },
|
|
167
174
|
{ value: 'restart', label: pc.yellow('Restart') },
|
|
@@ -169,14 +176,18 @@ async function runAction(r) {
|
|
|
169
176
|
{ value: 'ping', label: 'Ping' }
|
|
170
177
|
);
|
|
171
178
|
} else if (r.online) {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
179
|
+
// Remote, or local but started outside this manager (no PID to own) —
|
|
180
|
+
// either way the runner's own /api/shutdown|restart endpoints are
|
|
181
|
+
// reachable over the network via the primary's control routes.
|
|
182
|
+
options.push(
|
|
183
|
+
{ value: 'stop', label: pc.red('Stop') },
|
|
184
|
+
{ value: 'restart', label: pc.yellow('Restart') },
|
|
185
|
+
{ value: 'ping', label: 'Ping' }
|
|
176
186
|
);
|
|
177
|
-
|
|
178
|
-
} else {
|
|
187
|
+
} else if (r.local) {
|
|
179
188
|
options.push({ value: 'start', label: pc.green('Start') }, { value: 'ping', label: 'Ping' });
|
|
189
|
+
} else {
|
|
190
|
+
options.push({ value: 'ping', label: 'Ping' });
|
|
180
191
|
}
|
|
181
192
|
|
|
182
193
|
options.push(
|
|
@@ -194,15 +205,39 @@ async function runAction(r) {
|
|
|
194
205
|
const entry = startNode({ id: r.id, port, token: r.token });
|
|
195
206
|
clack.log.success(pc.green(`Started "${r.name}" on port ${port} (pid ${entry.pid})`));
|
|
196
207
|
} else if (action === 'stop') {
|
|
197
|
-
|
|
198
|
-
|
|
208
|
+
if (r.managed) {
|
|
209
|
+
const ok = stopNode(r.id);
|
|
210
|
+
clack.log.success(
|
|
211
|
+
ok ? pc.green(`Stopped "${r.name}"`) : pc.dim(`"${r.name}" was not running`)
|
|
212
|
+
);
|
|
213
|
+
} else {
|
|
214
|
+
const s = clack.spinner();
|
|
215
|
+
s.start(`Stopping "${r.name}"...`);
|
|
216
|
+
try {
|
|
217
|
+
await controlRunner(r.id, 'stop');
|
|
218
|
+
s.stop(pc.green(`Stopped "${r.name}"`));
|
|
219
|
+
} catch (e) {
|
|
220
|
+
s.stop(pc.red(`Could not stop "${r.name}": ${e.message}`));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
199
223
|
} else if (action === 'restart') {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
224
|
+
if (r.managed) {
|
|
225
|
+
const s = clack.spinner();
|
|
226
|
+
s.start(`Restarting "${r.name}"...`);
|
|
227
|
+
stopNode(r.id);
|
|
228
|
+
await new Promise((resolve) => setTimeout(resolve, 600));
|
|
229
|
+
const entry = startNode({ id: r.id, port, token: r.token });
|
|
230
|
+
s.stop(pc.green(`Restarted "${r.name}" (pid ${entry.pid})`));
|
|
231
|
+
} else {
|
|
232
|
+
const s = clack.spinner();
|
|
233
|
+
s.start(`Restarting "${r.name}"...`);
|
|
234
|
+
try {
|
|
235
|
+
await controlRunner(r.id, 'restart');
|
|
236
|
+
s.stop(pc.green(`Restarted "${r.name}"`));
|
|
237
|
+
} catch (e) {
|
|
238
|
+
s.stop(pc.red(`Could not restart "${r.name}": ${e.message}`));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
206
241
|
} else if (action === 'log') {
|
|
207
242
|
const entry = runnerProcess.loadRegistry()[r.id];
|
|
208
243
|
clack.note(entry?.logFile ?? '(no log file)', 'Log file');
|