@nmakarov/cli-toolkit 0.18.0 → 0.21.0
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 +9 -0
- package/dist/cli-runner.cjs +426 -97
- package/dist/cli-runner.cjs.map +1 -1
- package/dist/cli-runner.js +457 -128
- package/dist/cli-runner.js.map +1 -1
- package/dist/db.cjs +1 -1
- package/dist/db.cjs.map +1 -1
- package/dist/db.js +1 -1
- package/dist/db.js.map +1 -1
- package/dist/filedatabase.cjs.map +1 -1
- package/dist/filedatabase.js.map +1 -1
- package/dist/http-client2.cjs +6 -2
- package/dist/http-client2.cjs.map +1 -1
- package/dist/http-client2.js +6 -2
- package/dist/http-client2.js.map +1 -1
- package/dist/index.cjs +482 -96
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +469 -94
- package/dist/index.js.map +1 -1
- package/dist/init.cjs +16 -1
- package/dist/init.cjs.map +1 -1
- package/dist/init.js +16 -1
- package/dist/init.js.map +1 -1
- package/dist/mock-server.cjs.map +1 -1
- package/dist/mock-server.js.map +1 -1
- package/dist/params.cjs +16 -1
- package/dist/params.cjs.map +1 -1
- package/dist/params.js +16 -1
- package/dist/params.js.map +1 -1
- package/dist/tasks.cjs +458 -87
- package/dist/tasks.cjs.map +1 -1
- package/dist/tasks.js +478 -118
- package/dist/tasks.js.map +1 -1
- package/package.json +10 -3
- package/scripts/ssm/parse-cli.ts +35 -0
- package/scripts/ssm/ssm-admin.ts +151 -0
- package/scripts/ssm/ssm-pull.ts +150 -0
package/dist/index.cjs
CHANGED
|
@@ -932,11 +932,11 @@ function buildBreadcrumb(parts) {
|
|
|
932
932
|
if (parts.length === 1) return parts[0];
|
|
933
933
|
return parts.slice(1).map((part) => `\u2190 ${part}`).join(" ");
|
|
934
934
|
}
|
|
935
|
-
function buildDetailBreadcrumb(
|
|
936
|
-
if (
|
|
937
|
-
return suffix ? `\u2190 ${suffix}` :
|
|
935
|
+
function buildDetailBreadcrumb(path5, suffix = "") {
|
|
936
|
+
if (path5.length <= 1) {
|
|
937
|
+
return suffix ? `\u2190 ${suffix}` : path5[0] || "";
|
|
938
938
|
}
|
|
939
|
-
const breadcrumb = buildBreadcrumb(
|
|
939
|
+
const breadcrumb = buildBreadcrumb(path5);
|
|
940
940
|
return suffix ? `${breadcrumb} ${suffix}` : breadcrumb;
|
|
941
941
|
}
|
|
942
942
|
var init_utils = __esm({
|
|
@@ -1135,13 +1135,19 @@ __export(src_exports, {
|
|
|
1135
1135
|
h: () => import_react5.createElement,
|
|
1136
1136
|
joiEdateType: () => joiEdateType,
|
|
1137
1137
|
joiStringArrayType: () => joiStringArrayType,
|
|
1138
|
+
listAliveRunnerHeartbeats: () => listServicesRegistry,
|
|
1139
|
+
listServicesRegistry: () => listServicesRegistry,
|
|
1138
1140
|
listSources: () => listSources,
|
|
1139
1141
|
listTables: () => listTables,
|
|
1140
1142
|
load: () => load,
|
|
1141
1143
|
organizeFooterMessages: () => organizeFooterMessages,
|
|
1142
1144
|
queueToTableNames: () => queueToTableNames,
|
|
1145
|
+
registerInServicesRegistry: () => registerInServicesRegistry,
|
|
1146
|
+
registerRunnerHeartbeat: () => registerInServicesRegistry,
|
|
1143
1147
|
runNodeTaskScript: () => runNodeTaskScript,
|
|
1144
1148
|
runTasksLoop: () => runTasksLoop,
|
|
1149
|
+
runnerHeartbeatsTable: () => servicesRegistryTable,
|
|
1150
|
+
servicesRegistryTable: () => servicesRegistryTable,
|
|
1145
1151
|
setupContext: () => setupContext,
|
|
1146
1152
|
showListScreen: () => showListScreen,
|
|
1147
1153
|
showMenuScreen: () => showMenuScreen,
|
|
@@ -1149,6 +1155,11 @@ __export(src_exports, {
|
|
|
1149
1155
|
showMultiColumnListWithPreviewScreen: () => showMultiColumnListWithPreviewScreen,
|
|
1150
1156
|
showScreen: () => showScreen,
|
|
1151
1157
|
showWordGridScreen: () => showWordGridScreen,
|
|
1158
|
+
touchRunnerHeartbeat: () => touchServicesRegistry,
|
|
1159
|
+
touchServicesRegistry: () => touchServicesRegistry,
|
|
1160
|
+
unregisterRunnerHeartbeat: () => unregisterServicesRegistry,
|
|
1161
|
+
unregisterServicesRegistry: () => unregisterServicesRegistry,
|
|
1162
|
+
updateServicesRegistryMetadata: () => updateServicesRegistryMetadata,
|
|
1152
1163
|
updateTaskProgress: () => updateTaskProgress,
|
|
1153
1164
|
useCallback: () => import_react5.useCallback,
|
|
1154
1165
|
useEffect: () => import_react5.useEffect,
|
|
@@ -1981,7 +1992,7 @@ var Params = class _Params {
|
|
|
1981
1992
|
throw new ParamError(`default value "${defValObj.value}" type mismatch`);
|
|
1982
1993
|
}
|
|
1983
1994
|
type = type.default(defValObj.value);
|
|
1984
|
-
} else if (str.match(
|
|
1995
|
+
} else if (str.match(/\s*required\s*/)) {
|
|
1985
1996
|
type = type.required();
|
|
1986
1997
|
} else {
|
|
1987
1998
|
type = type.optional();
|
|
@@ -2057,6 +2068,8 @@ var Params = class _Params {
|
|
|
2057
2068
|
/**
|
|
2058
2069
|
* Get all parameters from definitions (main script).
|
|
2059
2070
|
* Same as getAllForModule("script", defs). Processes left-to-right for cross-parameter references.
|
|
2071
|
+
* Libraries should use {@link getAllForModule} with an explicit module name (or {@link runWithModule}
|
|
2072
|
+
* around {@link get}) so --showUsedParams groups usage correctly.
|
|
2060
2073
|
*/
|
|
2061
2074
|
getAll(defs) {
|
|
2062
2075
|
return this.getAllForModule("script", defs);
|
|
@@ -2093,6 +2106,19 @@ var Params = class _Params {
|
|
|
2093
2106
|
this._currentModule = prev;
|
|
2094
2107
|
}
|
|
2095
2108
|
}
|
|
2109
|
+
/**
|
|
2110
|
+
* Run a callback with {@link _currentModule} set so single {@link get} calls are tracked
|
|
2111
|
+
* under the same module (for --showUsedParams / getFiguredByModule).
|
|
2112
|
+
*/
|
|
2113
|
+
runWithModule(moduleName, fn) {
|
|
2114
|
+
const prev = this._currentModule;
|
|
2115
|
+
this._currentModule = moduleName;
|
|
2116
|
+
try {
|
|
2117
|
+
return fn();
|
|
2118
|
+
} finally {
|
|
2119
|
+
this._currentModule = prev;
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2096
2122
|
/**
|
|
2097
2123
|
* Infer module name from call stack: first caller outside params/index gives path like .../src/<moduleName>/...
|
|
2098
2124
|
*/
|
|
@@ -2106,9 +2132,9 @@ var Params = class _Params {
|
|
|
2106
2132
|
if (!parenMatch) continue;
|
|
2107
2133
|
const parts = parenMatch[1].split(":");
|
|
2108
2134
|
if (parts.length < 3) continue;
|
|
2109
|
-
const
|
|
2110
|
-
if (!
|
|
2111
|
-
const srcMatch =
|
|
2135
|
+
const path5 = parts.slice(0, -2).join(":").replace(/^file:\/\//, "");
|
|
2136
|
+
if (!path5 || path5.includes(paramsIndexPath)) continue;
|
|
2137
|
+
const srcMatch = path5.match(/[/\\]src[/\\]([^/\\]+)(?:[/\\]|$)/);
|
|
2112
2138
|
if (srcMatch) return srcMatch[1];
|
|
2113
2139
|
}
|
|
2114
2140
|
return "script";
|
|
@@ -3710,7 +3736,7 @@ async function dbFindAndConnect(context, dbNameOrConnectionString) {
|
|
|
3710
3736
|
dbConnectionString: "string",
|
|
3711
3737
|
dbProfile: "boolean default false"
|
|
3712
3738
|
};
|
|
3713
|
-
const paramsConfig = context.params.
|
|
3739
|
+
const paramsConfig = context.params.getAll(defs);
|
|
3714
3740
|
dbName = paramsConfig.dbName;
|
|
3715
3741
|
dbConnectionString = paramsConfig.dbConnectionString;
|
|
3716
3742
|
dbProfile = paramsConfig.dbProfile;
|
|
@@ -4096,6 +4122,12 @@ function toJsonColumn(value) {
|
|
|
4096
4122
|
return JSON.stringify(value);
|
|
4097
4123
|
}
|
|
4098
4124
|
|
|
4125
|
+
// src/tasks/servicesRegistry.ts
|
|
4126
|
+
var import_node_crypto2 = require("crypto");
|
|
4127
|
+
var import_promises = require("fs/promises");
|
|
4128
|
+
var import_node_os = __toESM(require("os"), 1);
|
|
4129
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
4130
|
+
|
|
4099
4131
|
// src/tasks/taskUtils.ts
|
|
4100
4132
|
var import_node_crypto = require("crypto");
|
|
4101
4133
|
function getDb(context) {
|
|
@@ -4114,6 +4146,12 @@ function queueToTableNames(queue) {
|
|
|
4114
4146
|
historyTable: `${queue}_history`
|
|
4115
4147
|
};
|
|
4116
4148
|
}
|
|
4149
|
+
function servicesRegistryTable(queue) {
|
|
4150
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(queue)) {
|
|
4151
|
+
throw new Error(`Invalid queue name "${queue}". Use letters, numbers, underscore only.`);
|
|
4152
|
+
}
|
|
4153
|
+
return `${queue}_services_registry`;
|
|
4154
|
+
}
|
|
4117
4155
|
async function ensureTaskTables(context, options = {}) {
|
|
4118
4156
|
const queue = options.queue ?? "tasks";
|
|
4119
4157
|
const recreate = options.recreate ?? false;
|
|
@@ -4150,18 +4188,6 @@ async function ensureTaskTables(context, options = {}) {
|
|
|
4150
4188
|
t.index(["target", "task"], `${tasksTable}_target_task_idx`);
|
|
4151
4189
|
});
|
|
4152
4190
|
}
|
|
4153
|
-
const tasksHasOpid = await db.schema.hasColumn(tasksTable, "opid");
|
|
4154
|
-
if (!tasksHasOpid) {
|
|
4155
|
-
await db.schema.alterTable(tasksTable, (t) => {
|
|
4156
|
-
t.text("opid");
|
|
4157
|
-
});
|
|
4158
|
-
}
|
|
4159
|
-
const tasksHasPausedAt = await db.schema.hasColumn(tasksTable, "paused_at");
|
|
4160
|
-
if (!tasksHasPausedAt) {
|
|
4161
|
-
await db.schema.alterTable(tasksTable, (t) => {
|
|
4162
|
-
t.timestamp("paused_at").defaultTo(null);
|
|
4163
|
-
});
|
|
4164
|
-
}
|
|
4165
4191
|
if (needsHistory) {
|
|
4166
4192
|
await db.schema.createTable(historyTable, (t) => {
|
|
4167
4193
|
t.uuid("id").notNullable();
|
|
@@ -4184,10 +4210,24 @@ async function ensureTaskTables(context, options = {}) {
|
|
|
4184
4210
|
t.index(["task", "created_at"], `${historyTable}_task_created_idx`);
|
|
4185
4211
|
});
|
|
4186
4212
|
}
|
|
4187
|
-
const
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4213
|
+
const registryTable = servicesRegistryTable(queue);
|
|
4214
|
+
const needsRegistry = !await db.tableExists(registryTable);
|
|
4215
|
+
if (needsRegistry) {
|
|
4216
|
+
await db.schema.createTable(registryTable, (t) => {
|
|
4217
|
+
t.uuid("id").primary().defaultTo(db.raw("uuid_generate_v4()"));
|
|
4218
|
+
t.uuid("instance_id").notNullable().unique();
|
|
4219
|
+
t.text("queue").notNullable();
|
|
4220
|
+
t.text("service_group").notNullable();
|
|
4221
|
+
t.text("service_name").notNullable();
|
|
4222
|
+
t.text("target").notNullable();
|
|
4223
|
+
t.text("hostname");
|
|
4224
|
+
t.integer("pid");
|
|
4225
|
+
t.json("metadata");
|
|
4226
|
+
t.timestamp("created_at").notNullable().defaultTo(db.fn.now());
|
|
4227
|
+
t.timestamp("last_seen_at").notNullable().defaultTo(db.fn.now());
|
|
4228
|
+
t.unique(["queue", "service_name"], `${registryTable}_queue_service_name_uniq`);
|
|
4229
|
+
t.index(["queue", "service_group", "last_seen_at"], `${registryTable}_queue_group_seen_idx`);
|
|
4230
|
+
t.index(["queue", "last_seen_at"], `${registryTable}_queue_seen_idx`);
|
|
4191
4231
|
});
|
|
4192
4232
|
}
|
|
4193
4233
|
}
|
|
@@ -4214,6 +4254,260 @@ async function updateTaskProgress(context, tasksTable, taskId, progress) {
|
|
|
4214
4254
|
});
|
|
4215
4255
|
}
|
|
4216
4256
|
|
|
4257
|
+
// src/tasks/servicesRegistry.ts
|
|
4258
|
+
function getDb2(context) {
|
|
4259
|
+
const db = context.db;
|
|
4260
|
+
if (!db) {
|
|
4261
|
+
throw new Error("Services registry requires context.db");
|
|
4262
|
+
}
|
|
4263
|
+
return db;
|
|
4264
|
+
}
|
|
4265
|
+
function parseMetadataColumn(value) {
|
|
4266
|
+
if (!value) return {};
|
|
4267
|
+
if (typeof value === "object" && !Array.isArray(value)) return value;
|
|
4268
|
+
if (typeof value === "string") {
|
|
4269
|
+
try {
|
|
4270
|
+
const p = JSON.parse(value);
|
|
4271
|
+
return p && typeof p === "object" && !Array.isArray(p) ? p : {};
|
|
4272
|
+
} catch {
|
|
4273
|
+
return {};
|
|
4274
|
+
}
|
|
4275
|
+
}
|
|
4276
|
+
return {};
|
|
4277
|
+
}
|
|
4278
|
+
var DEFAULT_GROUP_MAX_INSTANCES = {
|
|
4279
|
+
intake: 1,
|
|
4280
|
+
harvest: 1,
|
|
4281
|
+
loader: 0,
|
|
4282
|
+
photos: 0,
|
|
4283
|
+
photosprocessor: 0,
|
|
4284
|
+
ingest: 0
|
|
4285
|
+
};
|
|
4286
|
+
function sanitizeNamePart(raw) {
|
|
4287
|
+
const s = String(raw || "").trim().replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
4288
|
+
return s.slice(0, 80) || "runner";
|
|
4289
|
+
}
|
|
4290
|
+
function identityFilePath(identityDir, queue, serviceGroup) {
|
|
4291
|
+
const safeQ = sanitizeNamePart(queue);
|
|
4292
|
+
const safeG = sanitizeNamePart(serviceGroup);
|
|
4293
|
+
return import_node_path.default.join(identityDir, `${safeQ}_${safeG}.json`);
|
|
4294
|
+
}
|
|
4295
|
+
async function readIdentityFile(filePath) {
|
|
4296
|
+
try {
|
|
4297
|
+
const text = await (0, import_promises.readFile)(filePath, "utf8");
|
|
4298
|
+
const parsed = JSON.parse(text);
|
|
4299
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
4300
|
+
} catch {
|
|
4301
|
+
return {};
|
|
4302
|
+
}
|
|
4303
|
+
}
|
|
4304
|
+
async function writeIdentityFile(filePath, data) {
|
|
4305
|
+
await (0, import_promises.mkdir)(import_node_path.default.dirname(filePath), { recursive: true });
|
|
4306
|
+
await (0, import_promises.writeFile)(filePath, `${JSON.stringify(data, null, 2)}
|
|
4307
|
+
`, "utf8");
|
|
4308
|
+
}
|
|
4309
|
+
function resolveMaxInstances(serviceGroup, override) {
|
|
4310
|
+
if (override !== void 0 && Number.isFinite(override)) {
|
|
4311
|
+
return Math.max(0, Math.floor(Number(override)));
|
|
4312
|
+
}
|
|
4313
|
+
const g = serviceGroup.trim().toLowerCase();
|
|
4314
|
+
return DEFAULT_GROUP_MAX_INSTANCES[g] ?? 0;
|
|
4315
|
+
}
|
|
4316
|
+
async function countAliveInGroup(db, registryTable, queue, serviceGroup, staleMs, excludeInstanceId) {
|
|
4317
|
+
const cutoff = new Date(Date.now() - staleMs);
|
|
4318
|
+
let q = db(registryTable).where({ queue, service_group: serviceGroup }).where("last_seen_at", ">", cutoff);
|
|
4319
|
+
if (excludeInstanceId) {
|
|
4320
|
+
q = q.whereNot("instance_id", excludeInstanceId);
|
|
4321
|
+
}
|
|
4322
|
+
const row = await q.count("id as count").first();
|
|
4323
|
+
return Number(row?.count ?? 0);
|
|
4324
|
+
}
|
|
4325
|
+
function isUniqueViolation(error) {
|
|
4326
|
+
const code = error?.code ?? error?.errno;
|
|
4327
|
+
return code === "23505" || String(error?.message || "").includes("duplicate key");
|
|
4328
|
+
}
|
|
4329
|
+
async function registerInServicesRegistry(context, options) {
|
|
4330
|
+
const db = getDb2(context);
|
|
4331
|
+
const registryTable = servicesRegistryTable(options.queue);
|
|
4332
|
+
const serviceGroup = options.serviceGroup.trim();
|
|
4333
|
+
if (!serviceGroup) {
|
|
4334
|
+
throw new Error("registerInServicesRegistry: serviceGroup is required");
|
|
4335
|
+
}
|
|
4336
|
+
const identityPath = identityFilePath(options.identityDir, options.queue, serviceGroup);
|
|
4337
|
+
let identity = await readIdentityFile(identityPath);
|
|
4338
|
+
let instanceId = typeof identity.instanceId === "string" && identity.instanceId.trim() ? identity.instanceId.trim() : (0, import_node_crypto2.randomUUID)();
|
|
4339
|
+
identity.instanceId = instanceId;
|
|
4340
|
+
await writeIdentityFile(identityPath, identity);
|
|
4341
|
+
const hostname = import_node_os.default.hostname();
|
|
4342
|
+
const pid = typeof process.pid === "number" ? process.pid : null;
|
|
4343
|
+
const meta = toJsonColumn(options.metadata ?? null);
|
|
4344
|
+
const existing = await db(registryTable).where({ instance_id: instanceId }).first();
|
|
4345
|
+
if (existing) {
|
|
4346
|
+
await db(registryTable).where({ instance_id: instanceId }).update({
|
|
4347
|
+
target: options.target,
|
|
4348
|
+
hostname,
|
|
4349
|
+
pid,
|
|
4350
|
+
metadata: meta,
|
|
4351
|
+
last_seen_at: db.fn.now()
|
|
4352
|
+
});
|
|
4353
|
+
const serviceName = String(existing.service_name);
|
|
4354
|
+
identity.serviceName = serviceName;
|
|
4355
|
+
await writeIdentityFile(identityPath, identity);
|
|
4356
|
+
const reg = {
|
|
4357
|
+
instanceId,
|
|
4358
|
+
serviceName,
|
|
4359
|
+
serviceGroup,
|
|
4360
|
+
queue: options.queue,
|
|
4361
|
+
target: options.target,
|
|
4362
|
+
rowId: String(existing.id)
|
|
4363
|
+
};
|
|
4364
|
+
context.servicesRegistry = reg;
|
|
4365
|
+
context.runnerHeartbeat = reg;
|
|
4366
|
+
context.logger.info?.(
|
|
4367
|
+
`[services-registry] resumed instance_id=${instanceId} name=${serviceName} group=${serviceGroup} queue=${options.queue}`
|
|
4368
|
+
);
|
|
4369
|
+
return {
|
|
4370
|
+
instanceId,
|
|
4371
|
+
serviceName,
|
|
4372
|
+
serviceGroup,
|
|
4373
|
+
queue: options.queue,
|
|
4374
|
+
target: options.target,
|
|
4375
|
+
rowId: String(existing.id),
|
|
4376
|
+
registryTable
|
|
4377
|
+
};
|
|
4378
|
+
}
|
|
4379
|
+
const maxAllowed = resolveMaxInstances(serviceGroup, options.groupMaxInstances);
|
|
4380
|
+
const aliveOthers = await countAliveInGroup(
|
|
4381
|
+
db,
|
|
4382
|
+
registryTable,
|
|
4383
|
+
options.queue,
|
|
4384
|
+
serviceGroup,
|
|
4385
|
+
options.staleMs,
|
|
4386
|
+
instanceId
|
|
4387
|
+
);
|
|
4388
|
+
if (maxAllowed > 0 && aliveOthers >= maxAllowed) {
|
|
4389
|
+
const msg = `[services-registry] group limit reached for "${serviceGroup}": ${aliveOthers} alive (max ${maxAllowed}, queue=${options.queue}).`;
|
|
4390
|
+
if (options.enforceMaxInstances) {
|
|
4391
|
+
throw new Error(msg);
|
|
4392
|
+
}
|
|
4393
|
+
context.logger.warn?.(`${msg} Starting anyway (runnerEnforceMaxInstances=false).`);
|
|
4394
|
+
}
|
|
4395
|
+
const explicitName = options.serviceName?.trim();
|
|
4396
|
+
const fromFile = typeof identity.serviceName === "string" ? identity.serviceName.trim() : "";
|
|
4397
|
+
const hostBase = sanitizeNamePart(hostname);
|
|
4398
|
+
const groupBase = sanitizeNamePart(serviceGroup);
|
|
4399
|
+
const baseCandidates = [];
|
|
4400
|
+
if (explicitName) baseCandidates.push(sanitizeNamePart(explicitName));
|
|
4401
|
+
if (fromFile) baseCandidates.push(sanitizeNamePart(fromFile));
|
|
4402
|
+
baseCandidates.push(`${groupBase}-${hostBase}`);
|
|
4403
|
+
baseCandidates.push(groupBase);
|
|
4404
|
+
function* eachServiceNameCandidate(bases) {
|
|
4405
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4406
|
+
for (const rawBase of bases) {
|
|
4407
|
+
const base = sanitizeNamePart(rawBase);
|
|
4408
|
+
if (!base) continue;
|
|
4409
|
+
const seq = [base];
|
|
4410
|
+
for (let n = 2; n <= 500; n++) seq.push(`${base}-${n}`);
|
|
4411
|
+
for (const c of seq) {
|
|
4412
|
+
if (seen.has(c)) continue;
|
|
4413
|
+
seen.add(c);
|
|
4414
|
+
yield c;
|
|
4415
|
+
}
|
|
4416
|
+
}
|
|
4417
|
+
}
|
|
4418
|
+
let inserted;
|
|
4419
|
+
for (const candidate of eachServiceNameCandidate(baseCandidates)) {
|
|
4420
|
+
try {
|
|
4421
|
+
const rows = await db(registryTable).insert({
|
|
4422
|
+
instance_id: instanceId,
|
|
4423
|
+
queue: options.queue,
|
|
4424
|
+
service_group: serviceGroup,
|
|
4425
|
+
service_name: candidate,
|
|
4426
|
+
target: options.target,
|
|
4427
|
+
hostname,
|
|
4428
|
+
pid,
|
|
4429
|
+
metadata: meta,
|
|
4430
|
+
last_seen_at: db.fn.now()
|
|
4431
|
+
}).returning(["id", "service_name"]);
|
|
4432
|
+
const row = Array.isArray(rows) ? rows[0] : rows;
|
|
4433
|
+
if (row) {
|
|
4434
|
+
inserted = { id: String(row.id), service_name: String(row.service_name) };
|
|
4435
|
+
break;
|
|
4436
|
+
}
|
|
4437
|
+
} catch (error) {
|
|
4438
|
+
if (!isUniqueViolation(error)) {
|
|
4439
|
+
throw error;
|
|
4440
|
+
}
|
|
4441
|
+
}
|
|
4442
|
+
}
|
|
4443
|
+
if (!inserted) {
|
|
4444
|
+
throw new Error(
|
|
4445
|
+
`[services-registry] could not allocate a unique service_name for group=${serviceGroup} queue=${options.queue} (too many collisions).`
|
|
4446
|
+
);
|
|
4447
|
+
}
|
|
4448
|
+
identity.serviceName = inserted.service_name;
|
|
4449
|
+
await writeIdentityFile(identityPath, identity);
|
|
4450
|
+
const regNew = {
|
|
4451
|
+
instanceId,
|
|
4452
|
+
serviceName: inserted.service_name,
|
|
4453
|
+
serviceGroup,
|
|
4454
|
+
queue: options.queue,
|
|
4455
|
+
target: options.target,
|
|
4456
|
+
rowId: inserted.id
|
|
4457
|
+
};
|
|
4458
|
+
context.servicesRegistry = regNew;
|
|
4459
|
+
context.runnerHeartbeat = regNew;
|
|
4460
|
+
context.logger.info?.(
|
|
4461
|
+
`[services-registry] registered instance_id=${instanceId} name=${inserted.service_name} group=${serviceGroup} queue=${options.queue} target=${options.target}`
|
|
4462
|
+
);
|
|
4463
|
+
return {
|
|
4464
|
+
instanceId,
|
|
4465
|
+
serviceName: inserted.service_name,
|
|
4466
|
+
serviceGroup,
|
|
4467
|
+
queue: options.queue,
|
|
4468
|
+
target: options.target,
|
|
4469
|
+
rowId: inserted.id,
|
|
4470
|
+
registryTable
|
|
4471
|
+
};
|
|
4472
|
+
}
|
|
4473
|
+
async function touchServicesRegistry(context, registration) {
|
|
4474
|
+
const db = getDb2(context);
|
|
4475
|
+
const hostname = import_node_os.default.hostname();
|
|
4476
|
+
const pid = typeof process.pid === "number" ? process.pid : null;
|
|
4477
|
+
await db(registration.registryTable).where({ instance_id: registration.instanceId }).update({
|
|
4478
|
+
last_seen_at: db.fn.now(),
|
|
4479
|
+
hostname,
|
|
4480
|
+
pid
|
|
4481
|
+
});
|
|
4482
|
+
}
|
|
4483
|
+
async function updateServicesRegistryMetadata(context, registration, patch) {
|
|
4484
|
+
const db = getDb2(context);
|
|
4485
|
+
const row = await db(registration.registryTable).where({ instance_id: registration.instanceId }).first();
|
|
4486
|
+
const prev = parseMetadataColumn(row?.metadata);
|
|
4487
|
+
const merged = { ...prev, ...patch };
|
|
4488
|
+
await db(registration.registryTable).where({ instance_id: registration.instanceId }).update({
|
|
4489
|
+
metadata: toJsonColumn(merged),
|
|
4490
|
+
last_seen_at: db.fn.now()
|
|
4491
|
+
});
|
|
4492
|
+
context.logger.info?.(`[services-registry] metadata updated for ${registration.serviceName}`);
|
|
4493
|
+
}
|
|
4494
|
+
async function unregisterServicesRegistry(context, registration) {
|
|
4495
|
+
const db = getDb2(context);
|
|
4496
|
+
await db(registration.registryTable).where({ instance_id: registration.instanceId }).delete();
|
|
4497
|
+
context.logger.info?.(`[services-registry] unregistered name=${registration.serviceName} instance_id=${registration.instanceId}`);
|
|
4498
|
+
}
|
|
4499
|
+
async function listServicesRegistry(context, options = { queue: "tasks" }) {
|
|
4500
|
+
const db = getDb2(context);
|
|
4501
|
+
const staleMs = options.staleMs ?? 6e4;
|
|
4502
|
+
const cutoff = new Date(Date.now() - staleMs);
|
|
4503
|
+
const table = servicesRegistryTable(options.queue);
|
|
4504
|
+
let q = db(table).where("last_seen_at", ">", cutoff).orderBy([{ column: "service_group", order: "asc" }, { column: "service_name", order: "asc" }]);
|
|
4505
|
+
if (options.serviceGroup?.trim()) {
|
|
4506
|
+
q = q.where({ service_group: options.serviceGroup.trim() });
|
|
4507
|
+
}
|
|
4508
|
+
return await q;
|
|
4509
|
+
}
|
|
4510
|
+
|
|
4217
4511
|
// src/tasks/taskLogs.ts
|
|
4218
4512
|
function getLogsState(context) {
|
|
4219
4513
|
const holder = context;
|
|
@@ -4556,8 +4850,8 @@ var TaskShellCommand = class extends TaskMaster {
|
|
|
4556
4850
|
};
|
|
4557
4851
|
|
|
4558
4852
|
// src/tasks/coreTasks/TaskSystemInfo.ts
|
|
4559
|
-
var
|
|
4560
|
-
var
|
|
4853
|
+
var import_node_os2 = __toESM(require("os"), 1);
|
|
4854
|
+
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
4561
4855
|
function toGb(valueBytes) {
|
|
4562
4856
|
return `${(valueBytes / 1024 ** 3).toFixed(2)} GB`;
|
|
4563
4857
|
}
|
|
@@ -4565,7 +4859,7 @@ function toMb(valueBytes) {
|
|
|
4565
4859
|
return `${(valueBytes / 1024 ** 2).toFixed(2)} MB`;
|
|
4566
4860
|
}
|
|
4567
4861
|
async function getDiskStats() {
|
|
4568
|
-
const stats = await
|
|
4862
|
+
const stats = await import_promises2.default.statfs("/");
|
|
4569
4863
|
const total = Number(stats.bsize) * Number(stats.blocks);
|
|
4570
4864
|
const free = Number(stats.bsize) * Number(stats.bavail);
|
|
4571
4865
|
const used = total - free;
|
|
@@ -4578,10 +4872,10 @@ async function getDiskStats() {
|
|
|
4578
4872
|
var TaskSystemInfo = class extends TaskMaster {
|
|
4579
4873
|
async run() {
|
|
4580
4874
|
try {
|
|
4581
|
-
const totalMemory =
|
|
4582
|
-
const freeMemory =
|
|
4875
|
+
const totalMemory = import_node_os2.default.totalmem();
|
|
4876
|
+
const freeMemory = import_node_os2.default.freemem();
|
|
4583
4877
|
const usedMemory = totalMemory - freeMemory;
|
|
4584
|
-
const cpus =
|
|
4878
|
+
const cpus = import_node_os2.default.cpus();
|
|
4585
4879
|
const cpuUtilization = cpus.map((cpu) => {
|
|
4586
4880
|
const total = Object.values(cpu.times).reduce((acc, time) => acc + time, 0);
|
|
4587
4881
|
const usage = (total - cpu.times.idle) / total * 100;
|
|
@@ -4607,10 +4901,10 @@ var TaskSystemInfo = class extends TaskMaster {
|
|
|
4607
4901
|
utilization: cpuUtilization
|
|
4608
4902
|
},
|
|
4609
4903
|
runtime: {
|
|
4610
|
-
platform:
|
|
4611
|
-
arch:
|
|
4612
|
-
uptimeSec:
|
|
4613
|
-
hostname:
|
|
4904
|
+
platform: import_node_os2.default.platform(),
|
|
4905
|
+
arch: import_node_os2.default.arch(),
|
|
4906
|
+
uptimeSec: import_node_os2.default.uptime(),
|
|
4907
|
+
hostname: import_node_os2.default.hostname()
|
|
4614
4908
|
}
|
|
4615
4909
|
};
|
|
4616
4910
|
this.context.logger.info?.(`[TaskSystemInfo] collected system metrics (${this.task.id})`);
|
|
@@ -4843,7 +5137,7 @@ async function runNodeTaskScript(context, options) {
|
|
|
4843
5137
|
// src/tasks/index.ts
|
|
4844
5138
|
var LOCKED_BY_ERROR_MESSAGE = "locked by error";
|
|
4845
5139
|
var defaultTasksRegistry = TasksRegistry.withCoreTasks();
|
|
4846
|
-
function
|
|
5140
|
+
function getDb3(context) {
|
|
4847
5141
|
const db = context.db;
|
|
4848
5142
|
if (!db) {
|
|
4849
5143
|
throw new Error("Tasks component requires context.db. Initialize DB first and attach to context.");
|
|
@@ -4887,7 +5181,7 @@ async function signalRunningTasksStop(context, runningTaskInstances, allowanceMs
|
|
|
4887
5181
|
context.emitter.emit("stop", allowanceMs);
|
|
4888
5182
|
}
|
|
4889
5183
|
async function executeClaimedTask(context, tasksTable, historyTable, row, registry, runningTaskInstances) {
|
|
4890
|
-
const db =
|
|
5184
|
+
const db = getDb3(context);
|
|
4891
5185
|
const taskName = row.task;
|
|
4892
5186
|
const TaskClass = registry.get(taskName);
|
|
4893
5187
|
const { paused_at: _pausedAt, ...rowForHistory } = row;
|
|
@@ -4988,7 +5282,7 @@ async function executeClaimedTask(context, tasksTable, historyTable, row, regist
|
|
|
4988
5282
|
return { stopRunnerRequested, stopAllowanceMs };
|
|
4989
5283
|
}
|
|
4990
5284
|
async function claimNextRunnableTask(context, tasksTable, target, registry, scanLimit, taskNames) {
|
|
4991
|
-
const db =
|
|
5285
|
+
const db = getDb3(context);
|
|
4992
5286
|
let query = db(tasksTable).whereNull("started_at").whereNull("paused_at").where({ target }).orderByRaw("CASE WHEN past_due IS NULL THEN 1 ELSE 0 END ASC").orderBy([{ column: "priority", order: "desc" }]).orderByRaw("CASE WHEN completed_at IS NULL THEN 0 ELSE 1 END ASC").orderBy([{ column: "completed_at", order: "asc" }, { column: "created_at", order: "asc" }]).limit(scanLimit);
|
|
4993
5287
|
if (taskNames && taskNames.length > 0) {
|
|
4994
5288
|
query = query.whereIn("task", taskNames);
|
|
@@ -5034,25 +5328,76 @@ async function runTasksLoop(context, options) {
|
|
|
5034
5328
|
let stopRequested = false;
|
|
5035
5329
|
let stopAllowanceMs = 5e3;
|
|
5036
5330
|
context.__tasksRunnerStop = false;
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
)
|
|
5047
|
-
|
|
5048
|
-
|
|
5331
|
+
let registryReg = null;
|
|
5332
|
+
let registryInterval = null;
|
|
5333
|
+
const hbGroup = options.runnerServiceGroup?.trim();
|
|
5334
|
+
if (hbGroup) {
|
|
5335
|
+
const identityDir = options.runnerIdentityDir ?? "./data/runner-identities";
|
|
5336
|
+
const hbIntervalMs = options.runnerHeartbeatIntervalMs ?? 1e4;
|
|
5337
|
+
const staleMs = options.runnerHeartbeatStaleMs ?? 45e3;
|
|
5338
|
+
const defaultMeta = {
|
|
5339
|
+
component: "tasks-runner",
|
|
5340
|
+
allowedTasks: allowedTasks?.length ? allowedTasks.join(",") : "all"
|
|
5341
|
+
};
|
|
5342
|
+
registryReg = await registerInServicesRegistry(context, {
|
|
5343
|
+
queue,
|
|
5344
|
+
target,
|
|
5345
|
+
serviceGroup: hbGroup,
|
|
5346
|
+
serviceName: options.runnerServiceName,
|
|
5347
|
+
identityDir,
|
|
5348
|
+
staleMs,
|
|
5349
|
+
groupMaxInstances: options.runnerGroupMaxInstances,
|
|
5350
|
+
enforceMaxInstances: options.runnerEnforceMaxInstances ?? true,
|
|
5351
|
+
metadata: options.runnerMetadata ?? defaultMeta
|
|
5352
|
+
});
|
|
5353
|
+
registryInterval = setInterval(() => {
|
|
5354
|
+
void touchServicesRegistry(context, registryReg).catch((err) => {
|
|
5355
|
+
context.logger.warn?.(`[services-registry] touch failed: ${err?.message ?? String(err)}`);
|
|
5356
|
+
});
|
|
5357
|
+
}, hbIntervalMs);
|
|
5358
|
+
}
|
|
5359
|
+
try {
|
|
5360
|
+
while (!context.isStop() && !stopRequested && !context.__tasksRunnerStop) {
|
|
5361
|
+
if (!runningStopControlPromise) {
|
|
5362
|
+
const claimedStopTask = await claimNextRunnableTask(
|
|
5049
5363
|
context,
|
|
5050
5364
|
tasksTable,
|
|
5051
|
-
|
|
5052
|
-
claimedStopTask,
|
|
5365
|
+
target,
|
|
5053
5366
|
registry,
|
|
5054
|
-
|
|
5055
|
-
|
|
5367
|
+
10,
|
|
5368
|
+
["stopRunner", "stop"]
|
|
5369
|
+
);
|
|
5370
|
+
if (claimedStopTask) {
|
|
5371
|
+
runningStopControlPromise = executeClaimedTask(
|
|
5372
|
+
context,
|
|
5373
|
+
tasksTable,
|
|
5374
|
+
historyTable,
|
|
5375
|
+
claimedStopTask,
|
|
5376
|
+
registry,
|
|
5377
|
+
runningTaskInstances
|
|
5378
|
+
).then(async (outcome) => {
|
|
5379
|
+
if (outcome.stopRunnerRequested && !stopRequested) {
|
|
5380
|
+
stopRequested = true;
|
|
5381
|
+
stopAllowanceMs = outcome.stopAllowanceMs || 5e3;
|
|
5382
|
+
context.__tasksRunnerStop = true;
|
|
5383
|
+
await signalRunningTasksStop(context, runningTaskInstances, stopAllowanceMs);
|
|
5384
|
+
}
|
|
5385
|
+
}).finally(() => {
|
|
5386
|
+
runningStopControlPromise = null;
|
|
5387
|
+
});
|
|
5388
|
+
}
|
|
5389
|
+
}
|
|
5390
|
+
while (runningPromises.size < maxParallel) {
|
|
5391
|
+
const claimed = await claimNextRunnableTask(
|
|
5392
|
+
context,
|
|
5393
|
+
tasksTable,
|
|
5394
|
+
target,
|
|
5395
|
+
registry,
|
|
5396
|
+
scanLimit,
|
|
5397
|
+
allowedTasks
|
|
5398
|
+
);
|
|
5399
|
+
if (!claimed) break;
|
|
5400
|
+
const p = executeClaimedTask(context, tasksTable, historyTable, claimed, registry, runningTaskInstances).then(async (outcome) => {
|
|
5056
5401
|
if (outcome.stopRunnerRequested && !stopRequested) {
|
|
5057
5402
|
stopRequested = true;
|
|
5058
5403
|
stopAllowanceMs = outcome.stopAllowanceMs || 5e3;
|
|
@@ -5060,54 +5405,46 @@ async function runTasksLoop(context, options) {
|
|
|
5060
5405
|
await signalRunningTasksStop(context, runningTaskInstances, stopAllowanceMs);
|
|
5061
5406
|
}
|
|
5062
5407
|
}).finally(() => {
|
|
5063
|
-
|
|
5408
|
+
runningPromises.delete(p);
|
|
5064
5409
|
});
|
|
5410
|
+
runningPromises.add(p);
|
|
5411
|
+
}
|
|
5412
|
+
await sleepMs(pollMs);
|
|
5413
|
+
}
|
|
5414
|
+
if (context.isStop() && !stopRequested) {
|
|
5415
|
+
await signalRunningTasksStop(context, runningTaskInstances, 5e3);
|
|
5416
|
+
}
|
|
5417
|
+
if (runningPromises.size > 0) {
|
|
5418
|
+
if (stopRequested) {
|
|
5419
|
+
await Promise.race([
|
|
5420
|
+
Promise.allSettled(Array.from(runningPromises)),
|
|
5421
|
+
sleepMs(stopAllowanceMs).then(() => {
|
|
5422
|
+
context.logger.warn?.(
|
|
5423
|
+
`[tasks] stop allowance (${stopAllowanceMs}ms) reached; ${runningPromises.size} task(s) still running`
|
|
5424
|
+
);
|
|
5425
|
+
})
|
|
5426
|
+
]);
|
|
5427
|
+
} else {
|
|
5428
|
+
await Promise.allSettled(Array.from(runningPromises));
|
|
5065
5429
|
}
|
|
5066
5430
|
}
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
target,
|
|
5072
|
-
registry,
|
|
5073
|
-
scanLimit,
|
|
5074
|
-
allowedTasks
|
|
5075
|
-
);
|
|
5076
|
-
if (!claimed) break;
|
|
5077
|
-
const p = executeClaimedTask(context, tasksTable, historyTable, claimed, registry, runningTaskInstances).then(async (outcome) => {
|
|
5078
|
-
if (outcome.stopRunnerRequested && !stopRequested) {
|
|
5079
|
-
stopRequested = true;
|
|
5080
|
-
stopAllowanceMs = outcome.stopAllowanceMs || 5e3;
|
|
5081
|
-
context.__tasksRunnerStop = true;
|
|
5082
|
-
await signalRunningTasksStop(context, runningTaskInstances, stopAllowanceMs);
|
|
5083
|
-
}
|
|
5084
|
-
}).finally(() => {
|
|
5085
|
-
runningPromises.delete(p);
|
|
5086
|
-
});
|
|
5087
|
-
runningPromises.add(p);
|
|
5431
|
+
} finally {
|
|
5432
|
+
if (registryInterval) {
|
|
5433
|
+
clearInterval(registryInterval);
|
|
5434
|
+
registryInterval = null;
|
|
5088
5435
|
}
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
await Promise.race([
|
|
5097
|
-
Promise.allSettled(Array.from(runningPromises)),
|
|
5098
|
-
sleepMs(stopAllowanceMs).then(() => {
|
|
5099
|
-
context.logger.warn?.(
|
|
5100
|
-
`[tasks] stop allowance (${stopAllowanceMs}ms) reached; ${runningPromises.size} task(s) still running`
|
|
5101
|
-
);
|
|
5102
|
-
})
|
|
5103
|
-
]);
|
|
5104
|
-
} else {
|
|
5105
|
-
await Promise.allSettled(Array.from(runningPromises));
|
|
5436
|
+
if (registryReg) {
|
|
5437
|
+
await unregisterServicesRegistry(context, registryReg).catch((err) => {
|
|
5438
|
+
context.logger.warn?.(`[services-registry] unregister failed: ${err?.message ?? String(err)}`);
|
|
5439
|
+
});
|
|
5440
|
+
registryReg = null;
|
|
5441
|
+
delete context.servicesRegistry;
|
|
5442
|
+
delete context.runnerHeartbeat;
|
|
5106
5443
|
}
|
|
5107
5444
|
}
|
|
5108
5445
|
}
|
|
5109
5446
|
async function waitForTaskResult(context, taskId, options = {}) {
|
|
5110
|
-
const db =
|
|
5447
|
+
const db = getDb3(context);
|
|
5111
5448
|
const queue = options.queue ?? "tasks";
|
|
5112
5449
|
const timeoutMs = options.timeoutMs ?? 6e4;
|
|
5113
5450
|
const pollMs = options.pollMs ?? 500;
|
|
@@ -5135,6 +5472,14 @@ var TasksManager = class _TasksManager {
|
|
|
5135
5472
|
scanLimit;
|
|
5136
5473
|
allowedTasks;
|
|
5137
5474
|
registry;
|
|
5475
|
+
runnerServiceGroup;
|
|
5476
|
+
runnerServiceName;
|
|
5477
|
+
runnerIdentityDir;
|
|
5478
|
+
runnerHeartbeatIntervalMs;
|
|
5479
|
+
runnerHeartbeatStaleMs;
|
|
5480
|
+
runnerGroupMaxInstances;
|
|
5481
|
+
runnerEnforceMaxInstances;
|
|
5482
|
+
runnerMetadata;
|
|
5138
5483
|
constructor(context, options = {}) {
|
|
5139
5484
|
this.context = context;
|
|
5140
5485
|
this.queue = options.queue ?? "tasks";
|
|
@@ -5145,6 +5490,14 @@ var TasksManager = class _TasksManager {
|
|
|
5145
5490
|
this.scanLimit = options.scanLimit ?? 100;
|
|
5146
5491
|
this.allowedTasks = normalizeAllowedTasks(options.allowedTasks);
|
|
5147
5492
|
this.registry = normalizeRegistry(options.registry);
|
|
5493
|
+
this.runnerServiceGroup = options.runnerServiceGroup;
|
|
5494
|
+
this.runnerServiceName = options.runnerServiceName;
|
|
5495
|
+
this.runnerIdentityDir = options.runnerIdentityDir;
|
|
5496
|
+
this.runnerHeartbeatIntervalMs = options.runnerHeartbeatIntervalMs;
|
|
5497
|
+
this.runnerHeartbeatStaleMs = options.runnerHeartbeatStaleMs;
|
|
5498
|
+
this.runnerGroupMaxInstances = options.runnerGroupMaxInstances;
|
|
5499
|
+
this.runnerEnforceMaxInstances = options.runnerEnforceMaxInstances;
|
|
5500
|
+
this.runnerMetadata = options.runnerMetadata;
|
|
5148
5501
|
}
|
|
5149
5502
|
static init(context, options = {}) {
|
|
5150
5503
|
const defs = {
|
|
@@ -5154,7 +5507,14 @@ var TasksManager = class _TasksManager {
|
|
|
5154
5507
|
pollMs: "number default 1000",
|
|
5155
5508
|
maxParallel: "number default 1",
|
|
5156
5509
|
scanLimit: "number default 100",
|
|
5157
|
-
allowedTasks: "string"
|
|
5510
|
+
allowedTasks: "string",
|
|
5511
|
+
runnerServiceGroup: "string",
|
|
5512
|
+
runnerServiceName: "string",
|
|
5513
|
+
runnerIdentityDir: "string default ./data/runner-identities",
|
|
5514
|
+
runnerHeartbeatIntervalMs: "number default 10000",
|
|
5515
|
+
runnerHeartbeatStaleMs: "number default 45000",
|
|
5516
|
+
runnerGroupMaxInstances: "number",
|
|
5517
|
+
runnerEnforceMaxInstances: "boolean default true"
|
|
5158
5518
|
};
|
|
5159
5519
|
const discovered = context.params.getAllForModule(defs);
|
|
5160
5520
|
const resolved = {
|
|
@@ -5165,6 +5525,13 @@ var TasksManager = class _TasksManager {
|
|
|
5165
5525
|
maxParallel: discovered.maxParallel,
|
|
5166
5526
|
scanLimit: discovered.scanLimit,
|
|
5167
5527
|
allowedTasks: discovered.allowedTasks,
|
|
5528
|
+
runnerServiceGroup: discovered.runnerServiceGroup,
|
|
5529
|
+
runnerServiceName: discovered.runnerServiceName,
|
|
5530
|
+
runnerIdentityDir: discovered.runnerIdentityDir,
|
|
5531
|
+
runnerHeartbeatIntervalMs: discovered.runnerHeartbeatIntervalMs,
|
|
5532
|
+
runnerHeartbeatStaleMs: discovered.runnerHeartbeatStaleMs,
|
|
5533
|
+
runnerGroupMaxInstances: discovered.runnerGroupMaxInstances,
|
|
5534
|
+
runnerEnforceMaxInstances: discovered.runnerEnforceMaxInstances,
|
|
5168
5535
|
...options
|
|
5169
5536
|
};
|
|
5170
5537
|
return new _TasksManager(context, resolved);
|
|
@@ -5183,7 +5550,15 @@ var TasksManager = class _TasksManager {
|
|
|
5183
5550
|
maxParallel: options.maxParallel ?? this.maxParallel,
|
|
5184
5551
|
scanLimit: options.scanLimit ?? this.scanLimit,
|
|
5185
5552
|
allowedTasks: options.allowedTasks ?? this.allowedTasks,
|
|
5186
|
-
registry: options.registry ?? this.registry
|
|
5553
|
+
registry: options.registry ?? this.registry,
|
|
5554
|
+
runnerServiceGroup: options.runnerServiceGroup ?? this.runnerServiceGroup,
|
|
5555
|
+
runnerServiceName: options.runnerServiceName ?? this.runnerServiceName,
|
|
5556
|
+
runnerIdentityDir: options.runnerIdentityDir ?? this.runnerIdentityDir,
|
|
5557
|
+
runnerHeartbeatIntervalMs: options.runnerHeartbeatIntervalMs ?? this.runnerHeartbeatIntervalMs,
|
|
5558
|
+
runnerHeartbeatStaleMs: options.runnerHeartbeatStaleMs ?? this.runnerHeartbeatStaleMs,
|
|
5559
|
+
runnerGroupMaxInstances: options.runnerGroupMaxInstances ?? this.runnerGroupMaxInstances,
|
|
5560
|
+
runnerEnforceMaxInstances: options.runnerEnforceMaxInstances ?? this.runnerEnforceMaxInstances,
|
|
5561
|
+
runnerMetadata: options.runnerMetadata ?? this.runnerMetadata
|
|
5187
5562
|
});
|
|
5188
5563
|
}
|
|
5189
5564
|
};
|
|
@@ -5238,13 +5613,19 @@ var TasksManager = class _TasksManager {
|
|
|
5238
5613
|
h,
|
|
5239
5614
|
joiEdateType,
|
|
5240
5615
|
joiStringArrayType,
|
|
5616
|
+
listAliveRunnerHeartbeats,
|
|
5617
|
+
listServicesRegistry,
|
|
5241
5618
|
listSources,
|
|
5242
5619
|
listTables,
|
|
5243
5620
|
load,
|
|
5244
5621
|
organizeFooterMessages,
|
|
5245
5622
|
queueToTableNames,
|
|
5623
|
+
registerInServicesRegistry,
|
|
5624
|
+
registerRunnerHeartbeat,
|
|
5246
5625
|
runNodeTaskScript,
|
|
5247
5626
|
runTasksLoop,
|
|
5627
|
+
runnerHeartbeatsTable,
|
|
5628
|
+
servicesRegistryTable,
|
|
5248
5629
|
setupContext,
|
|
5249
5630
|
showListScreen,
|
|
5250
5631
|
showMenuScreen,
|
|
@@ -5252,6 +5633,11 @@ var TasksManager = class _TasksManager {
|
|
|
5252
5633
|
showMultiColumnListWithPreviewScreen,
|
|
5253
5634
|
showScreen,
|
|
5254
5635
|
showWordGridScreen,
|
|
5636
|
+
touchRunnerHeartbeat,
|
|
5637
|
+
touchServicesRegistry,
|
|
5638
|
+
unregisterRunnerHeartbeat,
|
|
5639
|
+
unregisterServicesRegistry,
|
|
5640
|
+
updateServicesRegistryMetadata,
|
|
5255
5641
|
updateTaskProgress,
|
|
5256
5642
|
useCallback,
|
|
5257
5643
|
useEffect,
|