bdy 1.23.3-stage → 1.23.4-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
|
@@ -25,6 +25,7 @@ class Agent extends events_1.default {
|
|
|
25
25
|
api;
|
|
26
26
|
socket;
|
|
27
27
|
manager;
|
|
28
|
+
updateStatusExpiry;
|
|
28
29
|
onRefresh;
|
|
29
30
|
constructor(id, host, token, service, target, tunneling, proxy, tags, api, disabled) {
|
|
30
31
|
super();
|
|
@@ -41,6 +42,7 @@ class Agent extends events_1.default {
|
|
|
41
42
|
this.tunnelsUpdating = false;
|
|
42
43
|
this.api = api;
|
|
43
44
|
this.manager = null;
|
|
45
|
+
this.updateStatusExpiry = null;
|
|
44
46
|
this.onRefresh = null;
|
|
45
47
|
this.socket = new client_1.default(host, id, token);
|
|
46
48
|
this.socket.on(tunnel_1.TUNNEL_SOCKET_EVENT.FETCH_SUCCESS, (data) => this._onSocketFetch(data));
|
|
@@ -56,6 +58,10 @@ class Agent extends events_1.default {
|
|
|
56
58
|
this.socket.destroy();
|
|
57
59
|
this.socket = null;
|
|
58
60
|
}
|
|
61
|
+
// Would fire on a socket that is already gone
|
|
62
|
+
if (this.updateStatusExpiry)
|
|
63
|
+
clearTimeout(this.updateStatusExpiry);
|
|
64
|
+
this.updateStatusExpiry = null;
|
|
59
65
|
this.manager = null;
|
|
60
66
|
this.onRefresh = null;
|
|
61
67
|
this.api = null;
|
|
@@ -260,8 +266,35 @@ class Agent extends events_1.default {
|
|
|
260
266
|
// previous value in place, which is why the front reads STARTED on an offline agent as
|
|
261
267
|
// an unknown outcome rather than as an update still running.
|
|
262
268
|
reportUpdateStatus(status) {
|
|
263
|
-
if (this.socket)
|
|
264
|
-
|
|
269
|
+
if (!this.socket)
|
|
270
|
+
return;
|
|
271
|
+
this.socket.setPendingAction(status);
|
|
272
|
+
this.expireUpdateStatusIn(status);
|
|
273
|
+
}
|
|
274
|
+
// Takes the outcome back off the record after a while, so it reads as the confirmation
|
|
275
|
+
// it is rather than as a standing fact about the agent. Done here rather than by hiding
|
|
276
|
+
// it in the front because nothing on the record dates the write: the only timestamps a
|
|
277
|
+
// front could compare against are the agent's boot time and its heartbeat, and neither
|
|
278
|
+
// is when this happened.
|
|
279
|
+
//
|
|
280
|
+
// A timer is sound for this where it would not be for the update itself: the process
|
|
281
|
+
// that reports an outcome is the one still running, so nothing has to survive a restart
|
|
282
|
+
// - and if it dies first, the next start() sends an empty action anyway.
|
|
283
|
+
expireUpdateStatusIn(status) {
|
|
284
|
+
if (this.updateStatusExpiry)
|
|
285
|
+
clearTimeout(this.updateStatusExpiry);
|
|
286
|
+
this.updateStatusExpiry = null;
|
|
287
|
+
// STARTED is not an outcome. It is what stays behind when a restart never lands, and
|
|
288
|
+
// clearing it would turn the one state the front can flag as unknown into silence.
|
|
289
|
+
if (status === tunnel_1.TUNNEL_AGENT_UPDATE_STATUS.STARTED)
|
|
290
|
+
return;
|
|
291
|
+
this.updateStatusExpiry = setTimeout(() => {
|
|
292
|
+
this.updateStatusExpiry = null;
|
|
293
|
+
this.ackAction();
|
|
294
|
+
}, utils_1.AGENT_UPDATE_STATUS_TTL_MS);
|
|
295
|
+
// A foreground tunnel reporting UNSUPPORTED exits as soon as it has acked, and must
|
|
296
|
+
// not be held open for the rest of the window just to tidy up after itself
|
|
297
|
+
this.updateStatusExpiry.unref();
|
|
265
298
|
}
|
|
266
299
|
// For a status with no ack to ride on - STARTED, reported while the download is still
|
|
267
300
|
// running. Passes null so that if the status has somehow already gone out, this does
|
|
@@ -141,6 +141,11 @@ class AgentManagerClass {
|
|
|
141
141
|
// Every path that gives up reports why as well as acking: the ack alone clears the
|
|
142
142
|
// request, which on the front is indistinguishable from an update that never ran.
|
|
143
143
|
const report = (status) => {
|
|
144
|
+
// Except when the agent is going away. There is nothing left to tell, and the write
|
|
145
|
+
// would land on top of the DELETE this process has not finished acting on - which
|
|
146
|
+
// is also how the swap below reports being cut short by one.
|
|
147
|
+
if (this.exiting)
|
|
148
|
+
return;
|
|
144
149
|
this.agent?.reportUpdateStatus(status);
|
|
145
150
|
return this.agent?.ackAction();
|
|
146
151
|
};
|
|
@@ -540,6 +545,12 @@ class AgentManagerClass {
|
|
|
540
545
|
}
|
|
541
546
|
async disableAgentAndExit(txt) {
|
|
542
547
|
logger_1.default.error(txt);
|
|
548
|
+
// Set before the first await, not just before the exit: uninstalling and unregistering
|
|
549
|
+
// both take a while, and a remote update arriving in that window would otherwise start
|
|
550
|
+
// downloading a release for an agent that is being taken apart - and could rename the
|
|
551
|
+
// new binary into place after the files it lives among have been removed. The update
|
|
552
|
+
// path already refuses to start while this is set.
|
|
553
|
+
this.exiting = true;
|
|
543
554
|
try {
|
|
544
555
|
await this.system.uninstall();
|
|
545
556
|
}
|
|
@@ -407,7 +407,12 @@ class AgentSystem {
|
|
|
407
407
|
// Last check before touching the live binary. The download and the smoke test take
|
|
408
408
|
// long enough for an uninstall to have run in the meantime, and finishing the swap
|
|
409
409
|
// then would put a binary back for an agent that is deliberately gone.
|
|
410
|
-
|
|
410
|
+
//
|
|
411
|
+
// The config file alone is not enough to tell: an uninstall removes it only after
|
|
412
|
+
// stopping the service and unregistering, so a delete that is under way still looks
|
|
413
|
+
// like a live install from here for as long as those take. The flag is set before
|
|
414
|
+
// any of that starts.
|
|
415
|
+
if (!(0, node_fs_1.existsSync)(this.getSystemConfigPath()) || manager_1.default.exiting) {
|
|
411
416
|
throw new Error(texts_1.LOG_AGENT_UPDATE_UNINSTALLED);
|
|
412
417
|
}
|
|
413
418
|
(0, node_fs_1.rmSync)(backup, { force: true });
|
package/distTs/src/utils.js
CHANGED
|
@@ -36,8 +36,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
40
|
-
exports.getGitName = exports.getGitEmail = exports.MCP_TOOL_CATEGORIES = exports.getBasicCommandTls = exports.getBasicCommandHttp = exports.getBasicCommandSandboxEndpoint = exports.getBasicCommandTcp = exports.getCurrentUser = exports.getServiceUser = exports.getRealTargetHost = exports.isWindows = exports.isLinux = exports.isOsx = exports.isDocker = exports.sleep = exports.getLatestVersion = exports.getVersionEnv = exports.getCurrentVersionWithoutEnv = exports.getVersionWithoutEnv = exports.getVersion = exports.isInstalledByChoco = exports.isInstalledByApt = exports.isInstalledByBrew = exports.isInstalledByNpm = exports.tryGetEmail = exports.execLocally = void 0;
|
|
39
|
+
exports.isDomainAvailable = exports.newCommand = exports.formatBytes = exports.formatHelp = exports.getPlatform = exports.getHostname = exports.isStringRegExp = exports.getWorkingDir = exports.getRootDir = exports.TARGET_ONLY_PORT_REGEX = exports.TARGET_HTTP_REGEX = exports.TARGET_TCP_TLS_REGEX = exports.ApiErrorTunnelsDisabled = exports.ApiErrorWorkspaceFlagged = exports.ApiErrorTunnelLimitReached = exports.ApiErrorAgentLimitReached = exports.ApiErrorDomainRestricted = exports.ApiErrorTargetInvalid = exports.ApiErrorWrongToken = exports.ApiErrorFailedToConnect = exports.ApiErrorAgentNotFound = exports.ARTIFACT_AUTH_TYPE = exports.ARTIFACT_TYPE = exports.SANDBOX_SNAPSHOT_STATUS = exports.SANDBOX_APP_STATUS = exports.SANDBOX_SETUP_STATUS = exports.SANDBOX_EXEC_STATUS = exports.SANDBOX_EXEC_RUNTIME = exports.SANDBOX_STATUS = exports.REST_API_ENDPOINT = exports.REST_API_REGION = exports.DEFAULT_SANDBOX_CP_USER = exports.ARTIFACT_DEFAULT_VERSION = exports.SUGGESTED_BROWSER_VERSION = exports.AGENT_UPDATE_STATUS_TTL_MS = exports.AGENT_UPDATE_PROBATION_MS = exports.AGENT_UPDATE_MAX_ATTEMPTS = exports.AGENT_FETCH_RETRY_MAX = exports.AGENT_FETCH_RETRY_MIN = exports.SSH_HANDSHAKE_TIMEOUT = exports.DEFAULT_TIMEOUT = exports.TUNNEL_HTTP_RETRY_AFTER = exports.TUNNEL_HTTP_MAX_INFLIGHT = exports.TUNNEL_HTTP_CB_MIN_REQUESTS = exports.TUNNEL_HTTP_CB_WINDOW = exports.TUNNEL_MAX_REQUEST_SIZE_TO_SYNC = exports.TUNNEL_HTTP_LOG_MAX_REQUESTS = exports.TUNNEL_HTTP_LOG_MAX_BODY = exports.TUNNEL_HTTP_RATE_WINDOW = exports.TUNNEL_HTTP_RATE_LIMIT = void 0;
|
|
40
|
+
exports.getGitName = exports.getGitEmail = exports.MCP_TOOL_CATEGORIES = exports.getBasicCommandTls = exports.getBasicCommandHttp = exports.getBasicCommandSandboxEndpoint = exports.getBasicCommandTcp = exports.getCurrentUser = exports.getServiceUser = exports.getRealTargetHost = exports.isWindows = exports.isLinux = exports.isOsx = exports.isDocker = exports.sleep = exports.getLatestVersion = exports.getVersionEnv = exports.getCurrentVersionWithoutEnv = exports.getVersionWithoutEnv = exports.getVersion = exports.isInstalledByChoco = exports.isInstalledByApt = exports.isInstalledByBrew = exports.isInstalledByNpm = exports.tryGetEmail = exports.execLocally = exports.getHomeDirectory = void 0;
|
|
41
41
|
exports.apiErrorCodeToClass = apiErrorCodeToClass;
|
|
42
42
|
exports.isFile = isFile;
|
|
43
43
|
exports.getAppWorkspaceUrl = getAppWorkspaceUrl;
|
|
@@ -92,6 +92,11 @@ exports.AGENT_UPDATE_MAX_ATTEMPTS = 3;
|
|
|
92
92
|
// only has to be read. Generous on purpose: it is only ever reached when the counter
|
|
93
93
|
// cannot be persisted, so it must not fire on an agent that is merely slow to come up.
|
|
94
94
|
exports.AGENT_UPDATE_PROBATION_MS = 30 * 60 * 1000;
|
|
95
|
+
// How long a reported update outcome stays on the agent record before the agent clears it
|
|
96
|
+
// again. An outcome is a confirmation for whoever is watching the update, not a property of
|
|
97
|
+
// the agent: nothing re-evaluates it, so one left in place would still claim a machine is
|
|
98
|
+
// missing admin rights long after that was fixed. The agent log keeps the durable record.
|
|
99
|
+
exports.AGENT_UPDATE_STATUS_TTL_MS = 30 * 1000;
|
|
95
100
|
exports.SUGGESTED_BROWSER_VERSION = '130.0.6723.69';
|
|
96
101
|
exports.ARTIFACT_DEFAULT_VERSION = 'latest';
|
|
97
102
|
exports.DEFAULT_SANDBOX_CP_USER = 'buddy';
|