@cloudnux/local-cloud-provider 0.12.0 → 0.14.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/dist/dev-console-plugin/index.d.ts +37 -2
- package/dist/dev-console-plugin/index.js +452 -249
- package/dist/dev-console-plugin/index.js.map +1 -1
- package/dist/index.js +191 -102
- package/dist/index.js.map +1 -1
- package/dist/queue-plugin/index.d.ts +2 -1
- package/dist/queue-plugin/index.js +187 -102
- package/dist/queue-plugin/index.js.map +1 -1
- package/dist/schedule-plugin/index.js +193 -118
- package/dist/schedule-plugin/index.js.map +1 -1
- package/dist/websocket-plugin/index.d.ts +10 -3
- package/dist/websocket-plugin/index.js +1063 -11
- package/dist/websocket-plugin/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
// src/schedule-plugin/core.ts
|
|
5
|
-
import * as fs2 from "fs/promises";
|
|
6
|
-
import chalk6 from "chalk";
|
|
7
|
-
import logSymbols4 from "log-symbols";
|
|
1
|
+
// src/logging/pretty-writer.ts
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { EOL as EOL2 } from "os";
|
|
8
4
|
|
|
9
5
|
// ../../../node_modules/lodash-es/_freeGlobal.js
|
|
10
6
|
var freeGlobal = typeof global == "object" && global && global.Object === Object && global;
|
|
@@ -828,20 +824,32 @@ var utils = {
|
|
|
828
824
|
};
|
|
829
825
|
var env = Object.assign(_env, utils);
|
|
830
826
|
|
|
831
|
-
// ../../utils/src/logging/index.ts
|
|
832
|
-
import chalk from "chalk";
|
|
833
|
-
import { EOL } from "os";
|
|
834
|
-
|
|
835
827
|
// ../../utils/src/logging/types.ts
|
|
836
828
|
var logLevels = {
|
|
837
829
|
fatal: -1,
|
|
838
830
|
error: 0,
|
|
839
831
|
warn: 1,
|
|
840
832
|
info: 2,
|
|
841
|
-
debug: 3
|
|
833
|
+
debug: 3,
|
|
834
|
+
trace: 4
|
|
842
835
|
};
|
|
843
836
|
|
|
844
837
|
// ../../utils/src/logging/error-to-string.ts
|
|
838
|
+
var safeJsonStringify = (value) => {
|
|
839
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
840
|
+
return JSON.stringify(value, (key, currentValue) => {
|
|
841
|
+
if (key === "constructor") return void 0;
|
|
842
|
+
if (typeof currentValue === "object" && currentValue !== null) {
|
|
843
|
+
if (seen.has(currentValue)) return "[Circular]";
|
|
844
|
+
seen.add(currentValue);
|
|
845
|
+
}
|
|
846
|
+
return currentValue;
|
|
847
|
+
});
|
|
848
|
+
};
|
|
849
|
+
var hasOwnConstructorProp = (value) => {
|
|
850
|
+
if (typeof value !== "object" || value === null) return false;
|
|
851
|
+
return Object.prototype.hasOwnProperty.call(value, "constructor");
|
|
852
|
+
};
|
|
845
853
|
var errorToString = (error) => {
|
|
846
854
|
if (error === null) return "Null error";
|
|
847
855
|
if (error === void 0) return "Undefined error";
|
|
@@ -851,13 +859,22 @@ var errorToString = (error) => {
|
|
|
851
859
|
`Message: ${error.message}`,
|
|
852
860
|
`Stack: ${error.stack || "No stack trace available"}`,
|
|
853
861
|
// Handle additional properties that might exist on custom errors
|
|
854
|
-
...Object.entries(error).filter(
|
|
862
|
+
...Object.entries(error).filter(
|
|
863
|
+
([key, value]) => !["name", "message", "stack"].includes(key) && !hasOwnConstructorProp(value)
|
|
864
|
+
).map(([key, value]) => `${key}: ${safeJsonStringify(value)}`)
|
|
855
865
|
].join("\n");
|
|
856
866
|
}
|
|
857
867
|
if (typeof error === "string") return error;
|
|
858
868
|
if (typeof error === "object") {
|
|
859
869
|
try {
|
|
860
|
-
return JSON.stringify(
|
|
870
|
+
return JSON.stringify(
|
|
871
|
+
error,
|
|
872
|
+
(key, value) => {
|
|
873
|
+
if (key === "constructor") return void 0;
|
|
874
|
+
return value;
|
|
875
|
+
},
|
|
876
|
+
2
|
|
877
|
+
);
|
|
861
878
|
} catch {
|
|
862
879
|
return `[Object that cannot be stringified: ${Object.prototype.toString.call(error)}]`;
|
|
863
880
|
}
|
|
@@ -865,69 +882,135 @@ var errorToString = (error) => {
|
|
|
865
882
|
return String(error);
|
|
866
883
|
};
|
|
867
884
|
|
|
885
|
+
// ../../utils/src/logging/writer.ts
|
|
886
|
+
import { EOL } from "os";
|
|
887
|
+
var jsonWriter = (entry) => {
|
|
888
|
+
process.stdout.write(JSON.stringify(entry) + EOL);
|
|
889
|
+
};
|
|
890
|
+
var _writer = jsonWriter;
|
|
891
|
+
function setWriter(writer) {
|
|
892
|
+
_writer = writer;
|
|
893
|
+
}
|
|
894
|
+
function getWriter() {
|
|
895
|
+
return _writer;
|
|
896
|
+
}
|
|
897
|
+
|
|
868
898
|
// ../../utils/src/logging/index.ts
|
|
869
|
-
var
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
`[${(/* @__PURE__ */ new Date()).toTimeString()}]`,
|
|
877
|
-
`${chalk.bgRed.white(" fatal ")} - ${module || "unknown module"} - ${requestId || "no request ID"} - ${EOL}`,
|
|
878
|
-
errorToString(message),
|
|
879
|
-
meta ? `${EOL}${JSON.stringify(meta, null, 2)}` : ""
|
|
880
|
-
);
|
|
881
|
-
}
|
|
882
|
-
},
|
|
883
|
-
error: (message, meta) => {
|
|
884
|
-
if (currentLogLevel >= logLevels.error) {
|
|
885
|
-
console.error(
|
|
886
|
-
`[${(/* @__PURE__ */ new Date()).toTimeString()}]`,
|
|
887
|
-
`${chalk.bgRed.white(" error ")} - ${module || "unknown module"} - ${requestId || "no request ID"} - ${EOL}`,
|
|
888
|
-
errorToString(message),
|
|
889
|
-
meta ? `${EOL}${JSON.stringify(meta, null, 2)}` : ""
|
|
890
|
-
);
|
|
891
|
-
}
|
|
892
|
-
},
|
|
893
|
-
warn: (message, meta) => {
|
|
894
|
-
if (currentLogLevel >= logLevels.warn) {
|
|
895
|
-
console.warn(
|
|
896
|
-
`[${(/* @__PURE__ */ new Date()).toTimeString()}]`,
|
|
897
|
-
`${chalk.bgYellow.black(" warn ")} - ${module || "unknown module"} - ${requestId || "no request ID"} - ${EOL}`,
|
|
898
|
-
errorToString(message),
|
|
899
|
-
meta ? `${EOL}${JSON.stringify(meta, null, 2)}` : ""
|
|
900
|
-
);
|
|
901
|
-
}
|
|
902
|
-
},
|
|
903
|
-
info: (message, meta) => {
|
|
904
|
-
if (currentLogLevel >= logLevels.info) {
|
|
905
|
-
console.info(
|
|
906
|
-
`[${(/* @__PURE__ */ new Date()).toTimeString()}]`,
|
|
907
|
-
`${chalk.bgBlue.white(" info ")} - ${module || "unknown module"} - ${requestId || "no request ID"} - ${EOL}`,
|
|
908
|
-
message,
|
|
909
|
-
meta ? `${EOL}${JSON.stringify(meta, null, 2)}` : ""
|
|
910
|
-
);
|
|
911
|
-
}
|
|
912
|
-
},
|
|
913
|
-
debug: (message, meta) => {
|
|
914
|
-
if (currentLogLevel >= logLevels.debug) {
|
|
915
|
-
console.debug(
|
|
916
|
-
`[${(/* @__PURE__ */ new Date()).toTimeString()}]`,
|
|
917
|
-
`${chalk.bgWhite.black(" debug ")} - ${module || "unknown module"} - ${requestId || "no request ID"} - ${EOL}`,
|
|
918
|
-
message,
|
|
919
|
-
meta ? `${EOL}${JSON.stringify(meta, null, 2)}` : ""
|
|
920
|
-
);
|
|
921
|
-
}
|
|
922
|
-
}
|
|
899
|
+
var levelValues = {
|
|
900
|
+
fatal: 70,
|
|
901
|
+
error: 60,
|
|
902
|
+
warn: 50,
|
|
903
|
+
info: 40,
|
|
904
|
+
debug: 30,
|
|
905
|
+
trace: 20
|
|
923
906
|
};
|
|
907
|
+
var currentLogLevel = 2;
|
|
908
|
+
var _module = "default";
|
|
909
|
+
var _requestId = "";
|
|
910
|
+
function writeLine(level, mergeObject, msg, bindings) {
|
|
911
|
+
getWriter()({
|
|
912
|
+
level: levelValues[level],
|
|
913
|
+
levelName: level,
|
|
914
|
+
time: Date.now(),
|
|
915
|
+
module: bindings.module || _module,
|
|
916
|
+
reqId: bindings.reqId || _requestId,
|
|
917
|
+
msg: level === "error" || level === "fatal" ? errorToString(msg) : msg,
|
|
918
|
+
...mergeObject ? { meta: mergeObject } : {}
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
function createLogger(bindings = {}) {
|
|
922
|
+
const currentLogLevelName = env("LOG_LEVEL")?.toLowerCase() ?? "info";
|
|
923
|
+
currentLogLevel = logLevels[currentLogLevelName] ?? logLevels.info;
|
|
924
|
+
return {
|
|
925
|
+
level: currentLogLevelName,
|
|
926
|
+
fatal: (mergeObject, msg) => {
|
|
927
|
+
if (currentLogLevel >= logLevels.fatal) {
|
|
928
|
+
typeof mergeObject === "string" || mergeObject instanceof Error ? writeLine("fatal", null, mergeObject, bindings) : writeLine("fatal", mergeObject, msg ?? "", bindings);
|
|
929
|
+
}
|
|
930
|
+
},
|
|
931
|
+
error: (mergeObject, msg) => {
|
|
932
|
+
if (currentLogLevel >= logLevels.error) {
|
|
933
|
+
typeof mergeObject === "string" || mergeObject instanceof Error ? writeLine("error", null, mergeObject, bindings) : writeLine("error", mergeObject, msg ?? "", bindings);
|
|
934
|
+
}
|
|
935
|
+
},
|
|
936
|
+
warn: (mergeObject, msg) => {
|
|
937
|
+
if (currentLogLevel >= logLevels.warn) {
|
|
938
|
+
typeof mergeObject === "string" ? writeLine("warn", null, mergeObject, bindings) : writeLine("warn", mergeObject, msg ?? "", bindings);
|
|
939
|
+
}
|
|
940
|
+
},
|
|
941
|
+
info: (mergeObject, msg) => {
|
|
942
|
+
if (currentLogLevel >= logLevels.info) {
|
|
943
|
+
typeof mergeObject === "string" ? writeLine("info", null, mergeObject, bindings) : writeLine("info", mergeObject, msg ?? "", bindings);
|
|
944
|
+
}
|
|
945
|
+
},
|
|
946
|
+
debug: (mergeObject, msg) => {
|
|
947
|
+
if (currentLogLevel >= logLevels.debug) {
|
|
948
|
+
typeof mergeObject === "string" ? writeLine("debug", null, mergeObject, bindings) : writeLine("debug", mergeObject, msg ?? "", bindings);
|
|
949
|
+
}
|
|
950
|
+
},
|
|
951
|
+
trace: (mergeObject, msg) => {
|
|
952
|
+
if (currentLogLevel >= logLevels.trace) {
|
|
953
|
+
typeof mergeObject === "string" ? writeLine("trace", null, mergeObject, bindings) : writeLine("trace", mergeObject, msg ?? "", bindings);
|
|
954
|
+
}
|
|
955
|
+
},
|
|
956
|
+
silent: () => {
|
|
957
|
+
},
|
|
958
|
+
child: (childBindings) => createLogger({ ...bindings, ...childBindings })
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
var logger = createLogger();
|
|
924
962
|
|
|
925
|
-
// src/
|
|
926
|
-
|
|
927
|
-
|
|
963
|
+
// src/logging/pretty-writer.ts
|
|
964
|
+
var levelColor = {
|
|
965
|
+
fatal: chalk.bgRed.white,
|
|
966
|
+
error: chalk.red,
|
|
967
|
+
warn: chalk.yellow,
|
|
968
|
+
info: chalk.cyan,
|
|
969
|
+
debug: chalk.gray,
|
|
970
|
+
trace: chalk.white
|
|
971
|
+
};
|
|
972
|
+
function formatTime(ms) {
|
|
973
|
+
return new Date(ms).toTimeString().slice(0, 8);
|
|
974
|
+
}
|
|
975
|
+
function formatMeta(meta) {
|
|
976
|
+
const { req, res, ...rest } = meta;
|
|
977
|
+
const lines = [];
|
|
978
|
+
if (req) {
|
|
979
|
+
const reqParts = [`${req.method} ${req.url}`];
|
|
980
|
+
if (req.remoteAddress) reqParts.push(`from ${req.remoteAddress}:${req.remotePort ?? ""}`);
|
|
981
|
+
if (req.headers) reqParts.push(`headers=${JSON.stringify(req.headers, null, 2)}`);
|
|
982
|
+
if (req.body !== void 0) reqParts.push(`body=${typeof req.body === "string" ? req.body : JSON.stringify(req.body, null, 2)}`);
|
|
983
|
+
lines.push(chalk.dim(" req: " + reqParts.join(" ")));
|
|
984
|
+
}
|
|
985
|
+
if (res) {
|
|
986
|
+
const resParts = [`${res.statusCode}`];
|
|
987
|
+
if (res.headers) resParts.push(`headers=${JSON.stringify(res.headers, null, 2)}`);
|
|
988
|
+
if (res.body !== void 0) resParts.push(`body=${typeof res.body === "string" ? res.body : JSON.stringify(res.body, null, 2)}`);
|
|
989
|
+
lines.push(chalk.dim(" res: " + resParts.join(" ")));
|
|
990
|
+
}
|
|
991
|
+
if (Object.keys(rest).length) {
|
|
992
|
+
lines.push(chalk.dim(" " + JSON.stringify(rest, null, 2)));
|
|
993
|
+
}
|
|
994
|
+
return lines.length ? EOL2 + lines.join(EOL2) : "";
|
|
995
|
+
}
|
|
996
|
+
var prettyWriter = (entry) => {
|
|
997
|
+
const color = levelColor[entry.levelName] ?? chalk.white;
|
|
998
|
+
const time = chalk.dim(formatTime(entry.time));
|
|
999
|
+
const level = color(entry.levelName.toUpperCase().padEnd(5));
|
|
1000
|
+
const module = chalk.magenta(entry.module);
|
|
1001
|
+
const reqId = entry.reqId ? chalk.dim(`[${entry.reqId}]`) + " " : "";
|
|
1002
|
+
const meta = entry.meta ? formatMeta(entry.meta) : "";
|
|
1003
|
+
process.stdout.write(`${time} ${level} ${module} ${reqId}- ${entry.msg}${meta}${EOL2}`);
|
|
1004
|
+
};
|
|
1005
|
+
setWriter(prettyWriter);
|
|
1006
|
+
|
|
1007
|
+
// src/schedule-plugin/plugin.ts
|
|
1008
|
+
import fsPlugin from "fastify-plugin";
|
|
1009
|
+
|
|
1010
|
+
// src/schedule-plugin/core.ts
|
|
1011
|
+
import * as fs2 from "fs/promises";
|
|
928
1012
|
|
|
929
1013
|
// src/schedule-plugin/cron-utils.ts
|
|
930
|
-
import chalk2 from "chalk";
|
|
931
1014
|
import { parseExpression } from "cron-parser";
|
|
932
1015
|
function parseCronExpression(cronExpression, lastRun, options = {}) {
|
|
933
1016
|
const {
|
|
@@ -959,7 +1042,7 @@ function parseCronExpression(cronExpression, lastRun, options = {}) {
|
|
|
959
1042
|
description: describeCronExpression(normalizedCron)
|
|
960
1043
|
};
|
|
961
1044
|
} catch (error) {
|
|
962
|
-
logger.error(
|
|
1045
|
+
logger.error(`Invalid cron expression: ${cronExpression} - ${error.message}`);
|
|
963
1046
|
const fallbackTime = /* @__PURE__ */ new Date();
|
|
964
1047
|
fallbackTime.setHours(fallbackTime.getHours() + 1);
|
|
965
1048
|
fallbackTime.setMinutes(0);
|
|
@@ -988,7 +1071,7 @@ function getNextExecutions(cronExpression, count = 5, options = {}) {
|
|
|
988
1071
|
}
|
|
989
1072
|
return executions;
|
|
990
1073
|
} catch (error) {
|
|
991
|
-
logger.error(
|
|
1074
|
+
logger.error(`Error getting next executions: ${error.message}`);
|
|
992
1075
|
return [];
|
|
993
1076
|
}
|
|
994
1077
|
}
|
|
@@ -1303,7 +1386,7 @@ var scheduleJob = (scheduler, state, executeJobFn) => {
|
|
|
1303
1386
|
updatedScheduler.timerId = setTimeout(() => {
|
|
1304
1387
|
executeJobFn(updatedScheduler);
|
|
1305
1388
|
}, timeUntilNextRun);
|
|
1306
|
-
logger.debug(
|
|
1389
|
+
logger.debug(`Scheduled job ${scheduler.job.name} to run in ${Math.round(timeUntilNextRun / 1e3)}s`);
|
|
1307
1390
|
}
|
|
1308
1391
|
return updatedScheduler;
|
|
1309
1392
|
};
|
|
@@ -1332,20 +1415,18 @@ var updateJobAfterExecution = (job, execution, config) => {
|
|
|
1332
1415
|
return updatedJob;
|
|
1333
1416
|
};
|
|
1334
1417
|
var handleExecutionError = (execution, error) => {
|
|
1335
|
-
logger.error(
|
|
1418
|
+
logger.error(`Job failed ${execution.jobId}: ${error.message}`);
|
|
1336
1419
|
return completeExecution(execution, void 0, error.message);
|
|
1337
1420
|
};
|
|
1338
1421
|
var handleExecutionSuccess = (execution, result) => {
|
|
1339
1422
|
const duration = execution.endTime ? execution.endTime.getTime() - execution.startTime.getTime() : 0;
|
|
1340
|
-
logger.debug(
|
|
1423
|
+
logger.debug(`Job completed in ${duration}ms`);
|
|
1341
1424
|
return completeExecution(execution, result);
|
|
1342
1425
|
};
|
|
1343
1426
|
|
|
1344
1427
|
// src/schedule-plugin/persistence.ts
|
|
1345
1428
|
import * as fs from "fs/promises";
|
|
1346
1429
|
import * as path from "path";
|
|
1347
|
-
import chalk4 from "chalk";
|
|
1348
|
-
import logSymbols2 from "log-symbols";
|
|
1349
1430
|
var createStateFilePath = (directory) => path.join(directory, "scheduler-state.json");
|
|
1350
1431
|
var createTempFilePath = (directory) => path.join(directory, `scheduler-state.${Date.now()}.temp.json`);
|
|
1351
1432
|
var serializeSchedulerState = (schedulers, executionHistory) => ({
|
|
@@ -1361,7 +1442,7 @@ var saveSchedulerState = async (state) => {
|
|
|
1361
1442
|
const tempFile = createTempFilePath(state.config.persistence.directory);
|
|
1362
1443
|
await fs.writeFile(tempFile, JSON.stringify(serializedState, null, 2), "utf8");
|
|
1363
1444
|
await fs.rename(tempFile, stateFile);
|
|
1364
|
-
logger.debug(
|
|
1445
|
+
logger.debug("Enhanced scheduler state saved");
|
|
1365
1446
|
} catch (error) {
|
|
1366
1447
|
logger.error("Failed to save scheduler state:", error);
|
|
1367
1448
|
}
|
|
@@ -1373,7 +1454,7 @@ var loadSchedulerStateData = async (directory) => {
|
|
|
1373
1454
|
return JSON.parse(data);
|
|
1374
1455
|
} catch (error) {
|
|
1375
1456
|
if (error.code === "ENOENT") {
|
|
1376
|
-
logger.debug(
|
|
1457
|
+
logger.debug("No previous scheduler state found - starting fresh");
|
|
1377
1458
|
} else {
|
|
1378
1459
|
logger.error("Failed to load scheduler state:", error);
|
|
1379
1460
|
}
|
|
@@ -1386,20 +1467,20 @@ var validateAndAdjustNextRun = (job, savedNextRun, lastRestartTime, config) => {
|
|
|
1386
1467
|
return calculateNextRunFromLastRun(job, job.lastRun, config);
|
|
1387
1468
|
}
|
|
1388
1469
|
if (savedNextRun <= now) {
|
|
1389
|
-
logger.debug(
|
|
1470
|
+
logger.debug(`Saved next run is in the past for ${job.name} - recalculating`);
|
|
1390
1471
|
return calculateNextRunFromLastRun(job, job.lastRun, config);
|
|
1391
1472
|
}
|
|
1392
1473
|
const timeSinceRestart = now.getTime() - lastRestartTime.getTime();
|
|
1393
1474
|
const isRapidRestart = timeSinceRestart < config.restartBehavior.rapidRestartThreshold;
|
|
1394
1475
|
if (isRapidRestart) {
|
|
1395
|
-
logger.debug(
|
|
1476
|
+
logger.debug(`Rapid restart detected for ${job.name} - preserving saved timing`);
|
|
1396
1477
|
return savedNextRun;
|
|
1397
1478
|
}
|
|
1398
1479
|
if (job.cronExpression || job.intervalMs) {
|
|
1399
1480
|
const expectedNextRun = calculateNextRunFromLastRun(job, job.lastRun, config);
|
|
1400
1481
|
const timeDiff = Math.abs(savedNextRun.getTime() - expectedNextRun.getTime());
|
|
1401
1482
|
if (timeDiff > config.restartBehavior.maxTimingDrift) {
|
|
1402
|
-
logger.debug(
|
|
1483
|
+
logger.debug(`Adjusting timing for ${job.name} - drift of ${Math.round(timeDiff / 1e3)}s detected`);
|
|
1403
1484
|
return expectedNextRun;
|
|
1404
1485
|
}
|
|
1405
1486
|
}
|
|
@@ -1413,7 +1494,7 @@ var restoreJobFromSavedData = (scheduler, savedJob, config, lastRestartTime) =>
|
|
|
1413
1494
|
lastRun: savedJob.lastRun ? new Date(savedJob.lastRun) : void 0
|
|
1414
1495
|
};
|
|
1415
1496
|
if (definitionChanged) {
|
|
1416
|
-
logger.debug(
|
|
1497
|
+
logger.debug(`Job definition changed: ${savedJob.name} - recalculating schedule`);
|
|
1417
1498
|
updatedJob.nextRun = calculateNextRunFromLastRun(updatedJob, updatedJob.lastRun, config);
|
|
1418
1499
|
} else {
|
|
1419
1500
|
const savedNextRun = savedJob.nextRun ? new Date(savedJob.nextRun) : void 0;
|
|
@@ -1423,7 +1504,7 @@ var restoreJobFromSavedData = (scheduler, savedJob, config, lastRestartTime) =>
|
|
|
1423
1504
|
const result = parseCronExpression(updatedJob.cronExpression, updatedJob.lastRun, {
|
|
1424
1505
|
timezone: updatedJob.timezone
|
|
1425
1506
|
});
|
|
1426
|
-
logger.debug(
|
|
1507
|
+
logger.debug(`Job restored: ${savedJob.name} - ${result.description} - next: ${updatedJob.nextRun.toLocaleString()}`);
|
|
1427
1508
|
}
|
|
1428
1509
|
return { ...scheduler, job: updatedJob };
|
|
1429
1510
|
};
|
|
@@ -1453,20 +1534,18 @@ var loadSchedulerState = async (schedulers, config, lastRestartTime) => {
|
|
|
1453
1534
|
}
|
|
1454
1535
|
}
|
|
1455
1536
|
const executionHistory = stateData.executions ? restoreExecutionHistory(stateData.executions) : [];
|
|
1456
|
-
logger.debug(
|
|
1537
|
+
logger.debug(`Enhanced scheduler state loaded (saved at ${stateData.savedAt})`);
|
|
1457
1538
|
return { schedulers: restoredSchedulers, executionHistory };
|
|
1458
1539
|
};
|
|
1459
1540
|
|
|
1460
1541
|
// src/schedule-plugin/cleanup.ts
|
|
1461
|
-
import chalk5 from "chalk";
|
|
1462
|
-
import logSymbols3 from "log-symbols";
|
|
1463
1542
|
var cleanupExecutionHistory = (state) => {
|
|
1464
1543
|
if (state.executionHistory.length > state.config.cleanup.maxExecutionHistory) {
|
|
1465
1544
|
const removed = state.executionHistory.splice(
|
|
1466
1545
|
0,
|
|
1467
1546
|
state.executionHistory.length - state.config.cleanup.maxExecutionHistory
|
|
1468
1547
|
);
|
|
1469
|
-
logger.debug(
|
|
1548
|
+
logger.debug(`Cleaned up ${removed.length} old execution records`);
|
|
1470
1549
|
return removed;
|
|
1471
1550
|
}
|
|
1472
1551
|
return [];
|
|
@@ -1533,11 +1612,11 @@ var createSchedulerFunctions = (state) => {
|
|
|
1533
1612
|
const { canExecute, reason } = canExecuteJob(scheduler, state);
|
|
1534
1613
|
if (!canExecute) {
|
|
1535
1614
|
if (reason === "Maximum concurrent executions reached") {
|
|
1536
|
-
logger.warn(
|
|
1615
|
+
logger.warn(`Delaying job ${scheduler.job.name} - ${reason}`);
|
|
1537
1616
|
scheduler.job.nextRun = new Date(Date.now() + 3e4);
|
|
1538
1617
|
scheduleJobFn(scheduler);
|
|
1539
1618
|
} else if (reason === "Job reached maximum runs") {
|
|
1540
|
-
logger.info(
|
|
1619
|
+
logger.info(`Job ${scheduler.job.name} reached max runs (${scheduler.job.maxRuns})`);
|
|
1541
1620
|
}
|
|
1542
1621
|
return;
|
|
1543
1622
|
}
|
|
@@ -1546,7 +1625,7 @@ var createSchedulerFunctions = (state) => {
|
|
|
1546
1625
|
state.executionHistory.push(execution);
|
|
1547
1626
|
scheduler.isRunning = true;
|
|
1548
1627
|
state.runningExecutions++;
|
|
1549
|
-
logger.info(
|
|
1628
|
+
logger.info(`Executing job ${scheduler.job.name} (${execution.id})`);
|
|
1550
1629
|
try {
|
|
1551
1630
|
const result = await executeJobWithTimeout(
|
|
1552
1631
|
scheduler.handler,
|
|
@@ -1606,20 +1685,18 @@ var initializeScheduler = async (state, scheduleJobFn) => {
|
|
|
1606
1685
|
scheduleJobFn(scheduler);
|
|
1607
1686
|
}
|
|
1608
1687
|
}
|
|
1609
|
-
logger.debug(
|
|
1688
|
+
logger.debug(`Scheduler initialized: ${Object.keys(state.schedulers).length} jobs loaded`);
|
|
1610
1689
|
} catch (error) {
|
|
1611
|
-
logger.error(
|
|
1690
|
+
logger.error(`Failed to initialize scheduler: ${error.message}`);
|
|
1612
1691
|
throw error;
|
|
1613
1692
|
}
|
|
1614
1693
|
};
|
|
1615
1694
|
|
|
1616
1695
|
// src/schedule-plugin/jobs.ts
|
|
1617
|
-
import chalk7 from "chalk";
|
|
1618
|
-
import logSymbols5 from "log-symbols";
|
|
1619
1696
|
var validateJobDefinition = (jobDef) => {
|
|
1620
1697
|
const expressionType = detectExpressionType(jobDef.cronExpression);
|
|
1621
1698
|
if (expressionType === "unknown") {
|
|
1622
|
-
logger.error(
|
|
1699
|
+
logger.error(`Invalid cron expression for job: ${jobDef.name}`);
|
|
1623
1700
|
throw new Error(`Invalid cron expression for job: ${jobDef.name}`);
|
|
1624
1701
|
}
|
|
1625
1702
|
};
|
|
@@ -1631,11 +1708,11 @@ var createJobFromDefinition = (jobDef, config) => {
|
|
|
1631
1708
|
const result = parseCronExpression(cronExpression, void 0, {
|
|
1632
1709
|
timezone: jobDef.timezone ?? config.cron.defaultTimezone
|
|
1633
1710
|
});
|
|
1634
|
-
logger.debug(
|
|
1711
|
+
logger.debug(`Job ${jobDef.name}: ${result.description} - Next: ${result.nextRun.toLocaleString()}`);
|
|
1635
1712
|
const upcoming = getNextExecutions(cronExpression, 3, {
|
|
1636
1713
|
timezone: jobDef.timezone ?? config.cron.defaultTimezone
|
|
1637
1714
|
});
|
|
1638
|
-
logger.debug(
|
|
1715
|
+
logger.debug(`Upcoming: ${upcoming.map((d) => d.toLocaleTimeString()).join(", ")}`);
|
|
1639
1716
|
}
|
|
1640
1717
|
const job = {
|
|
1641
1718
|
id: generateJobId(),
|
|
@@ -1755,8 +1832,6 @@ var registerAllRoutes = (app, state, executeJobFn, scheduleJobFn) => {
|
|
|
1755
1832
|
};
|
|
1756
1833
|
|
|
1757
1834
|
// src/schedule-plugin/decorator.ts
|
|
1758
|
-
import chalk8 from "chalk";
|
|
1759
|
-
import logSymbols6 from "log-symbols";
|
|
1760
1835
|
var isValidJobName = (jobName) => {
|
|
1761
1836
|
return typeof jobName === "string" && jobName.length > 0 && /^[a-zA-Z0-9_-]+$/.test(jobName);
|
|
1762
1837
|
};
|
|
@@ -1786,7 +1861,7 @@ var createSchedulerManager = ({
|
|
|
1786
1861
|
validateJobDefinition(jobDefinition);
|
|
1787
1862
|
const existingJob = Object.values(state.schedulers).find((s) => s.job.name === jobDefinition.name);
|
|
1788
1863
|
if (existingJob) {
|
|
1789
|
-
logger.warn(
|
|
1864
|
+
logger.warn(`Job already exists: ${jobDefinition.name}.`);
|
|
1790
1865
|
return existingJob.job.id;
|
|
1791
1866
|
}
|
|
1792
1867
|
const job = createJobFromDefinition(jobDefinition, config);
|
|
@@ -1795,10 +1870,10 @@ var createSchedulerManager = ({
|
|
|
1795
1870
|
if (job.enabled) {
|
|
1796
1871
|
scheduleJobFn(scheduler);
|
|
1797
1872
|
}
|
|
1798
|
-
logger.info(
|
|
1873
|
+
logger.info(`Job added: ${jobDefinition.name} (${job.id})`);
|
|
1799
1874
|
return job.id;
|
|
1800
1875
|
} catch (error) {
|
|
1801
|
-
logger.error(
|
|
1876
|
+
logger.error(`Failed to add job ${jobDefinition.name}: ${error.message}`);
|
|
1802
1877
|
throw error;
|
|
1803
1878
|
}
|
|
1804
1879
|
};
|
|
@@ -1810,15 +1885,15 @@ var createSchedulerManager = ({
|
|
|
1810
1885
|
throw new Error(`Job '${jobName}' does not exist`);
|
|
1811
1886
|
}
|
|
1812
1887
|
if (scheduler.isRunning) {
|
|
1813
|
-
logger.warn(
|
|
1888
|
+
logger.warn(`Removing job that is currently running: ${jobName}`);
|
|
1814
1889
|
}
|
|
1815
1890
|
if (scheduler.timerId) {
|
|
1816
1891
|
clearTimeout(scheduler.timerId);
|
|
1817
1892
|
}
|
|
1818
1893
|
delete state.schedulers[scheduler.job.id];
|
|
1819
|
-
logger.info(
|
|
1894
|
+
logger.info(`Job removed: ${jobName}`);
|
|
1820
1895
|
} catch (error) {
|
|
1821
|
-
logger.error(
|
|
1896
|
+
logger.error(`Failed to remove job ${jobName}: ${error.message}`);
|
|
1822
1897
|
throw error;
|
|
1823
1898
|
}
|
|
1824
1899
|
};
|
|
@@ -1830,8 +1905,8 @@ var createSchedulerManager = ({
|
|
|
1830
1905
|
return false;
|
|
1831
1906
|
}
|
|
1832
1907
|
};
|
|
1833
|
-
const listJobs = (
|
|
1834
|
-
return Object.values(state.schedulers).filter((s) => !
|
|
1908
|
+
const listJobs = (module) => {
|
|
1909
|
+
return Object.values(state.schedulers).filter((s) => !module || s.job.module === module).map((s) => s.job.name).sort();
|
|
1835
1910
|
};
|
|
1836
1911
|
const getJobStats = (jobName) => {
|
|
1837
1912
|
try {
|
|
@@ -1850,14 +1925,14 @@ var createSchedulerManager = ({
|
|
|
1850
1925
|
throw new Error(`Job '${jobName}' does not exist`);
|
|
1851
1926
|
}
|
|
1852
1927
|
if (scheduler.job.enabled) {
|
|
1853
|
-
logger.debug(
|
|
1928
|
+
logger.debug(`Job is already enabled: ${jobName}`);
|
|
1854
1929
|
return;
|
|
1855
1930
|
}
|
|
1856
1931
|
scheduler.job.enabled = true;
|
|
1857
1932
|
scheduleJobFn(scheduler);
|
|
1858
|
-
logger.info(
|
|
1933
|
+
logger.info(`Job enabled: ${jobName}`);
|
|
1859
1934
|
} catch (error) {
|
|
1860
|
-
logger.error(
|
|
1935
|
+
logger.error(`Failed to enable job ${jobName}: ${error.message}`);
|
|
1861
1936
|
throw error;
|
|
1862
1937
|
}
|
|
1863
1938
|
};
|
|
@@ -1869,7 +1944,7 @@ var createSchedulerManager = ({
|
|
|
1869
1944
|
throw new Error(`Job '${jobName}' does not exist`);
|
|
1870
1945
|
}
|
|
1871
1946
|
if (!scheduler.job.enabled) {
|
|
1872
|
-
logger.debug(
|
|
1947
|
+
logger.debug(`Job is already disabled: ${jobName}`);
|
|
1873
1948
|
return;
|
|
1874
1949
|
}
|
|
1875
1950
|
scheduler.job.enabled = false;
|
|
@@ -1877,9 +1952,9 @@ var createSchedulerManager = ({
|
|
|
1877
1952
|
clearTimeout(scheduler.timerId);
|
|
1878
1953
|
scheduler.timerId = void 0;
|
|
1879
1954
|
}
|
|
1880
|
-
logger.info(
|
|
1955
|
+
logger.info(`Job disabled: ${jobName}`);
|
|
1881
1956
|
} catch (error) {
|
|
1882
|
-
logger.error(
|
|
1957
|
+
logger.error(`Failed to disable job ${jobName}: ${error.message}`);
|
|
1883
1958
|
throw error;
|
|
1884
1959
|
}
|
|
1885
1960
|
};
|
|
@@ -1894,9 +1969,9 @@ var createSchedulerManager = ({
|
|
|
1894
1969
|
throw new Error(`Job '${jobName}' is already running`);
|
|
1895
1970
|
}
|
|
1896
1971
|
setImmediate(() => executeJob(scheduler));
|
|
1897
|
-
logger.info(
|
|
1972
|
+
logger.info(`Job triggered: ${jobName}`);
|
|
1898
1973
|
} catch (error) {
|
|
1899
|
-
logger.error(
|
|
1974
|
+
logger.error(`Failed to trigger job ${jobName}: ${error.message}`);
|
|
1900
1975
|
throw error;
|
|
1901
1976
|
}
|
|
1902
1977
|
};
|