bdy 1.23.9-dev → 1.23.10-dev
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/distTs/package.json
CHANGED
|
@@ -139,6 +139,7 @@ class Agent extends events_1.default {
|
|
|
139
139
|
try {
|
|
140
140
|
if (data.agent.action)
|
|
141
141
|
await this.makeAction(data.agent.action);
|
|
142
|
+
this.reclearLostUpdateStatus(data.agent.action);
|
|
142
143
|
const filtered = (data.tunnels || []).filter((t) => !!t.domain);
|
|
143
144
|
this.refreshTunnels(filtered);
|
|
144
145
|
}
|
|
@@ -290,12 +291,50 @@ class Agent extends events_1.default {
|
|
|
290
291
|
return;
|
|
291
292
|
this.updateStatusExpiry = setTimeout(() => {
|
|
292
293
|
this.updateStatusExpiry = null;
|
|
293
|
-
this.
|
|
294
|
+
this.queueUpdateStatusClear();
|
|
294
295
|
}, utils_1.AGENT_UPDATE_STATUS_TTL_MS);
|
|
295
296
|
// A foreground tunnel reporting UNSUPPORTED exits as soon as it has acked, and must
|
|
296
297
|
// not be held open for the rest of the window just to tidy up after itself
|
|
297
298
|
this.updateStatusExpiry.unref();
|
|
298
299
|
}
|
|
300
|
+
// Queued rather than sent, because a fetch of our own here would go out within
|
|
301
|
+
// milliseconds of refreshIn15's tick: this expiry and that interval are both armed when
|
|
302
|
+
// the process starts, and the ttl is a multiple of the interval. The backend writes the
|
|
303
|
+
// whole agent row per request, so the tick - which carries no action at all - rewrites
|
|
304
|
+
// the field this clear just emptied, and the outcome is back with nobody left to remove
|
|
305
|
+
// it. Riding the next scheduled fetch keeps it to one write per tick.
|
|
306
|
+
queueUpdateStatusClear() {
|
|
307
|
+
if (!this.socket)
|
|
308
|
+
return;
|
|
309
|
+
// An outcome reported in the meantime is the newer truth and has a window of its own
|
|
310
|
+
if (this.socket.pendingAction !== null)
|
|
311
|
+
return;
|
|
312
|
+
this.socket.setPendingAction('');
|
|
313
|
+
}
|
|
314
|
+
// An outcome still on the record after its window is one whose clear did not survive -
|
|
315
|
+
// see queueUpdateStatusClear for how that happens, and note it can equally be a status
|
|
316
|
+
// left behind by a process that died before its expiry ever fired. Either way nothing
|
|
317
|
+
// dates the value, so it would sit there until the next update request: queue the clear
|
|
318
|
+
// again and let the fetch after this one carry it.
|
|
319
|
+
reclearLostUpdateStatus(action) {
|
|
320
|
+
if (typeof action !== 'string')
|
|
321
|
+
return;
|
|
322
|
+
const statuses = Object.values(tunnel_1.TUNNEL_AGENT_UPDATE_STATUS);
|
|
323
|
+
if (!statuses.includes(action))
|
|
324
|
+
return;
|
|
325
|
+
// Never an outcome, and the one value the front reads as an unknown result
|
|
326
|
+
if (action === tunnel_1.TUNNEL_AGENT_UPDATE_STATUS.STARTED)
|
|
327
|
+
return;
|
|
328
|
+
// Still inside the window this status is being shown for
|
|
329
|
+
if (this.updateStatusExpiry)
|
|
330
|
+
return;
|
|
331
|
+
this.queueUpdateStatusClear();
|
|
332
|
+
// Sent from here rather than left for the next scheduled fetch, unlike the expiry above:
|
|
333
|
+
// this runs on a fetch response, which is as far from the next refresh tick as the
|
|
334
|
+
// schedule ever gets, so there is nothing to collide with. Waiting for two more fetches
|
|
335
|
+
// would leave a confirmation standing for a minute and a half.
|
|
336
|
+
this.ackAction();
|
|
337
|
+
}
|
|
299
338
|
// For a status with no ack to ride on - STARTED, reported while the download is still
|
|
300
339
|
// running. Passes null so that if the status has somehow already gone out, this does
|
|
301
340
|
// not overwrite it with an empty action.
|
|
@@ -178,6 +178,8 @@ commandSandboxCreate.action(async (options) => {
|
|
|
178
178
|
output_1.default.cyan(result.identifier);
|
|
179
179
|
output_1.default.dim('SSH: ', false);
|
|
180
180
|
output_1.default.cyan(`ssh ${result.ssh_host} -p ${result.ssh_port}`);
|
|
181
|
+
output_1.default.dim('SSH via CLI: ', false);
|
|
182
|
+
output_1.default.cyan(`bdy sb ssh ${result.identifier}`);
|
|
181
183
|
output_1.default.dim('Web terminal: ', false);
|
|
182
184
|
output_1.default.cyan(result.html_url);
|
|
183
185
|
output_1.default.green(texts_1.TXT_SANDBOX_CREATED);
|
|
@@ -44,6 +44,7 @@ commandSandboxGet.action(async (identifier, options) => {
|
|
|
44
44
|
? `ssh ${sandbox.ssh_host} -p ${sandbox.ssh_port}`
|
|
45
45
|
: '-',
|
|
46
46
|
],
|
|
47
|
+
['SSH via CLI', sandbox.identifier ? `bdy sb ssh ${sandbox.identifier}` : '-']
|
|
47
48
|
];
|
|
48
49
|
if (sandbox.endpoints && sandbox.endpoints.length > 0) {
|
|
49
50
|
data.push([
|