bullmq-dash 0.2.5 → 0.2.7
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/index.js +142 -122
- package/dist/index.js.map +9 -9
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -276,7 +276,8 @@ var profileSchema = z.object({
|
|
|
276
276
|
}).strict().optional(),
|
|
277
277
|
pollInterval: z.coerce.number().int().positive().optional(),
|
|
278
278
|
prefix: z.string().optional(),
|
|
279
|
-
queues: z.array(z.string()).optional()
|
|
279
|
+
queues: z.array(z.string()).optional(),
|
|
280
|
+
retentionMs: z.coerce.number().int().positive().optional()
|
|
280
281
|
}).strict();
|
|
281
282
|
var profilesFileSchema = z.object({
|
|
282
283
|
defaultProfile: z.string().optional(),
|
|
@@ -408,6 +409,7 @@ function parseRedisUrl(input) {
|
|
|
408
409
|
}
|
|
409
410
|
|
|
410
411
|
// src/config.ts
|
|
412
|
+
var DEFAULT_RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
|
|
411
413
|
var configSchema = z2.object({
|
|
412
414
|
redis: z2.object({
|
|
413
415
|
host: z2.string().default("localhost"),
|
|
@@ -419,7 +421,8 @@ var configSchema = z2.object({
|
|
|
419
421
|
}),
|
|
420
422
|
pollInterval: z2.coerce.number().int().positive().default(3000),
|
|
421
423
|
prefix: z2.string().default("bull"),
|
|
422
|
-
queueNames: z2.array(z2.string()).optional()
|
|
424
|
+
queueNames: z2.array(z2.string()).optional(),
|
|
425
|
+
retentionMs: z2.coerce.number().int().positive().default(DEFAULT_RETENTION_MS)
|
|
423
426
|
});
|
|
424
427
|
var packageVersion = null;
|
|
425
428
|
var HELP_TEXT = `
|
|
@@ -631,28 +634,33 @@ Examples:
|
|
|
631
634
|
var RESOURCE_COMMANDS = new Set(["queues", "jobs", "schedulers"]);
|
|
632
635
|
var ACTIONS = new Set(["list", "get", "retry", "delete"]);
|
|
633
636
|
function extractSubcommand(argv) {
|
|
634
|
-
const
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
for (let i = 0;i < argv.length; i++) {
|
|
638
|
-
if (donePositionals) {
|
|
639
|
-
flagArgv.push(argv[i]);
|
|
640
|
-
continue;
|
|
641
|
-
}
|
|
642
|
-
const arg = argv[i];
|
|
643
|
-
if (arg.startsWith("-")) {
|
|
644
|
-
donePositionals = true;
|
|
645
|
-
flagArgv.push(arg);
|
|
646
|
-
continue;
|
|
647
|
-
}
|
|
648
|
-
positionals.push(arg);
|
|
637
|
+
const firstFlagIndex = argv.findIndex((arg) => arg.startsWith("-"));
|
|
638
|
+
if (firstFlagIndex === -1) {
|
|
639
|
+
return { positionals: argv, flagArgv: [] };
|
|
649
640
|
}
|
|
650
|
-
return {
|
|
641
|
+
return {
|
|
642
|
+
positionals: argv.slice(0, firstFlagIndex),
|
|
643
|
+
flagArgv: argv.slice(firstFlagIndex)
|
|
644
|
+
};
|
|
651
645
|
}
|
|
652
646
|
function showSubcommandHelp(text) {
|
|
653
647
|
console.log(text);
|
|
654
648
|
process.exit(0);
|
|
655
649
|
}
|
|
650
|
+
function assertArgCount(positionals, count, usage) {
|
|
651
|
+
if (positionals.length > count) {
|
|
652
|
+
writeError(`Unexpected arguments: ${positionals.slice(count).join(" ")}`, "CONFIG_ERROR", `Usage: ${usage}`);
|
|
653
|
+
process.exit(2);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
function getRequiredArg(positionals, index, name, usage) {
|
|
657
|
+
const arg = positionals[index];
|
|
658
|
+
if (!arg) {
|
|
659
|
+
writeError(`Missing required argument: <${name}>`, "CONFIG_ERROR", `Usage: ${usage}`);
|
|
660
|
+
process.exit(2);
|
|
661
|
+
}
|
|
662
|
+
return arg;
|
|
663
|
+
}
|
|
656
664
|
function parseSubcommand(positionals, help, jobState, pageSize, since, name, dryRun, yes = false) {
|
|
657
665
|
if (positionals.length === 0)
|
|
658
666
|
return;
|
|
@@ -684,24 +692,15 @@ function parseSubcommand(positionals, help, jobState, pageSize, since, name, dry
|
|
|
684
692
|
if (action === "list") {
|
|
685
693
|
if (help)
|
|
686
694
|
showSubcommandHelp(QUEUES_LIST_HELP);
|
|
687
|
-
|
|
688
|
-
writeError(`Unexpected arguments: ${positionals.slice(2).join(" ")}`, "CONFIG_ERROR", "Usage: queues list [options]");
|
|
689
|
-
process.exit(2);
|
|
690
|
-
}
|
|
695
|
+
assertArgCount(positionals, 2, "queues list [options]");
|
|
691
696
|
return { kind: "queues-list" };
|
|
692
697
|
}
|
|
693
698
|
if (action === "delete") {
|
|
694
699
|
if (help)
|
|
695
700
|
showSubcommandHelp(QUEUES_DELETE_HELP);
|
|
696
|
-
const
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
process.exit(2);
|
|
700
|
-
}
|
|
701
|
-
if (positionals.length > 3) {
|
|
702
|
-
writeError(`Unexpected arguments: ${positionals.slice(3).join(" ")}`, "CONFIG_ERROR", "Usage: queues delete <queue> [--dry-run] [--yes]");
|
|
703
|
-
process.exit(2);
|
|
704
|
-
}
|
|
701
|
+
const usage = "queues delete <queue> [--dry-run] [--yes]";
|
|
702
|
+
const queue = getRequiredArg(positionals, 2, "queue", usage);
|
|
703
|
+
assertArgCount(positionals, 3, usage);
|
|
705
704
|
return { kind: "queues-delete", queue, dryRun, yes };
|
|
706
705
|
}
|
|
707
706
|
writeError(`Invalid action '${action}' for queues`, "CONFIG_ERROR", "Available actions: list, delete. Use --help for usage.");
|
|
@@ -711,44 +710,26 @@ function parseSubcommand(positionals, help, jobState, pageSize, since, name, dry
|
|
|
711
710
|
if (action === "list") {
|
|
712
711
|
if (help)
|
|
713
712
|
showSubcommandHelp(JOBS_LIST_HELP);
|
|
714
|
-
const
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
process.exit(2);
|
|
718
|
-
}
|
|
719
|
-
if (positionals.length > 3) {
|
|
720
|
-
writeError(`Unexpected arguments: ${positionals.slice(3).join(" ")}`, "CONFIG_ERROR", "Usage: jobs list <queue> [--job-state <state>] [--page-size <n>]");
|
|
721
|
-
process.exit(2);
|
|
722
|
-
}
|
|
713
|
+
const usage = "jobs list <queue> [--job-state <state>] [--page-size <n>]";
|
|
714
|
+
const queue = getRequiredArg(positionals, 2, "queue", usage);
|
|
715
|
+
assertArgCount(positionals, 3, usage);
|
|
723
716
|
return { kind: "jobs-list", queue, jobState, pageSize };
|
|
724
717
|
}
|
|
725
718
|
if (action === "get") {
|
|
726
719
|
if (help)
|
|
727
720
|
showSubcommandHelp(JOBS_GET_HELP);
|
|
728
|
-
const
|
|
729
|
-
const
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
process.exit(2);
|
|
733
|
-
}
|
|
734
|
-
if (positionals.length > 4) {
|
|
735
|
-
writeError(`Unexpected arguments: ${positionals.slice(4).join(" ")}`, "CONFIG_ERROR", "Usage: jobs get <queue> <job-id>");
|
|
736
|
-
process.exit(2);
|
|
737
|
-
}
|
|
721
|
+
const usage = "jobs get <queue> <job-id>";
|
|
722
|
+
const queue = getRequiredArg(positionals, 2, "queue", usage);
|
|
723
|
+
const jobId = getRequiredArg(positionals, 3, "job-id", usage);
|
|
724
|
+
assertArgCount(positionals, 4, usage);
|
|
738
725
|
return { kind: "jobs-get", queue, jobId };
|
|
739
726
|
}
|
|
740
727
|
if (action === "retry") {
|
|
741
728
|
if (help)
|
|
742
729
|
showSubcommandHelp(JOBS_RETRY_HELP);
|
|
743
|
-
const
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
process.exit(2);
|
|
747
|
-
}
|
|
748
|
-
if (positionals.length > 3) {
|
|
749
|
-
writeError(`Unexpected arguments: ${positionals.slice(3).join(" ")}`, "CONFIG_ERROR", "Usage: jobs retry <queue> --job-state failed [options]");
|
|
750
|
-
process.exit(2);
|
|
751
|
-
}
|
|
730
|
+
const usage = "jobs retry <queue> --job-state failed [--since <duration>] [--name <pattern>] [--dry-run]";
|
|
731
|
+
const queue = getRequiredArg(positionals, 2, "queue", usage);
|
|
732
|
+
assertArgCount(positionals, 3, usage);
|
|
752
733
|
if (!jobState) {
|
|
753
734
|
writeError("--job-state is required for 'jobs retry'", "CONFIG_ERROR", "Use --job-state failed. Other states are not currently supported.");
|
|
754
735
|
process.exit(2);
|
|
@@ -766,30 +747,18 @@ function parseSubcommand(positionals, help, jobState, pageSize, since, name, dry
|
|
|
766
747
|
if (action === "list") {
|
|
767
748
|
if (help)
|
|
768
749
|
showSubcommandHelp(SCHEDULERS_LIST_HELP);
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
process.exit(2);
|
|
773
|
-
}
|
|
774
|
-
if (positionals.length > 3) {
|
|
775
|
-
writeError(`Unexpected arguments: ${positionals.slice(3).join(" ")}`, "CONFIG_ERROR", "Usage: schedulers list <queue> [--page-size <n>]");
|
|
776
|
-
process.exit(2);
|
|
777
|
-
}
|
|
750
|
+
const usage = "schedulers list <queue> [--page-size <n>]";
|
|
751
|
+
const queue = getRequiredArg(positionals, 2, "queue", usage);
|
|
752
|
+
assertArgCount(positionals, 3, usage);
|
|
778
753
|
return { kind: "schedulers-list", queue, pageSize };
|
|
779
754
|
}
|
|
780
755
|
if (action === "get") {
|
|
781
756
|
if (help)
|
|
782
757
|
showSubcommandHelp(SCHEDULERS_GET_HELP);
|
|
783
|
-
const
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
process.exit(2);
|
|
788
|
-
}
|
|
789
|
-
if (positionals.length > 4) {
|
|
790
|
-
writeError(`Unexpected arguments: ${positionals.slice(4).join(" ")}`, "CONFIG_ERROR", "Usage: schedulers get <queue> <scheduler-id>");
|
|
791
|
-
process.exit(2);
|
|
792
|
-
}
|
|
758
|
+
const usage = "schedulers get <queue> <scheduler-id>";
|
|
759
|
+
const queue = getRequiredArg(positionals, 2, "queue", usage);
|
|
760
|
+
const schedulerId = getRequiredArg(positionals, 3, "scheduler-id", usage);
|
|
761
|
+
assertArgCount(positionals, 4, usage);
|
|
793
762
|
return { kind: "schedulers-get", queue, schedulerId };
|
|
794
763
|
}
|
|
795
764
|
writeError(`Invalid action '${action}' for schedulers`, "CONFIG_ERROR", "Available actions: list, get. Use --help for usage.");
|
|
@@ -985,7 +954,8 @@ function loadConfig(cliArgs, profile) {
|
|
|
985
954
|
},
|
|
986
955
|
pollInterval: cliArgs.pollInterval ?? p?.pollInterval,
|
|
987
956
|
prefix: cliArgs.prefix ?? p?.prefix,
|
|
988
|
-
queueNames: cliArgs.queues ?? p?.queues
|
|
957
|
+
queueNames: cliArgs.queues ?? p?.queues,
|
|
958
|
+
retentionMs: p?.retentionMs
|
|
989
959
|
};
|
|
990
960
|
const result = configSchema.safeParse(raw);
|
|
991
961
|
if (!result.success) {
|
|
@@ -1182,7 +1152,14 @@ async function deleteQueue(queueName, dryRun = false) {
|
|
|
1182
1152
|
// src/data/jobs.ts
|
|
1183
1153
|
var PAGE_SIZE = 25;
|
|
1184
1154
|
var DEFAULT_MAX_RESULTS = 1000;
|
|
1185
|
-
var SYNC_JOB_TYPES = [
|
|
1155
|
+
var SYNC_JOB_TYPES = [
|
|
1156
|
+
"active",
|
|
1157
|
+
"waiting",
|
|
1158
|
+
"completed",
|
|
1159
|
+
"failed",
|
|
1160
|
+
"delayed",
|
|
1161
|
+
"prioritized"
|
|
1162
|
+
];
|
|
1186
1163
|
var SYNC_PAGE_SIZE = 5000;
|
|
1187
1164
|
var VALID_JOB_STATUSES = ["wait", "active", "completed", "failed", "delayed"];
|
|
1188
1165
|
async function getAllJobs(queueName, status, maxResults = DEFAULT_MAX_RESULTS, includeData = false) {
|
|
@@ -1754,13 +1731,24 @@ CREATE TABLE IF NOT EXISTS jobs (
|
|
|
1754
1731
|
state TEXT NOT NULL,
|
|
1755
1732
|
timestamp INTEGER,
|
|
1756
1733
|
data_preview TEXT,
|
|
1734
|
+
removed_at INTEGER,
|
|
1757
1735
|
PRIMARY KEY (queue, id)
|
|
1758
1736
|
);
|
|
1759
1737
|
|
|
1760
1738
|
CREATE INDEX IF NOT EXISTS idx_jobs_queue_state ON jobs(queue, state);
|
|
1761
1739
|
CREATE INDEX IF NOT EXISTS idx_jobs_name ON jobs(name);
|
|
1762
1740
|
CREATE INDEX IF NOT EXISTS idx_jobs_timestamp ON jobs(timestamp);
|
|
1741
|
+
CREATE INDEX IF NOT EXISTS idx_jobs_active
|
|
1742
|
+
ON jobs(queue, state, timestamp) WHERE removed_at IS NULL;
|
|
1763
1743
|
`;
|
|
1744
|
+
function migrateRemovedAtColumn(database) {
|
|
1745
|
+
const cols = database.prepare("PRAGMA table_info(jobs)").all();
|
|
1746
|
+
if (cols.length === 0)
|
|
1747
|
+
return;
|
|
1748
|
+
if (cols.some((c) => c.name === "removed_at"))
|
|
1749
|
+
return;
|
|
1750
|
+
database.exec("ALTER TABLE jobs ADD COLUMN removed_at INTEGER");
|
|
1751
|
+
}
|
|
1764
1752
|
var FTS_SCHEMA = `
|
|
1765
1753
|
CREATE VIRTUAL TABLE IF NOT EXISTS jobs_fts USING fts5(
|
|
1766
1754
|
id,
|
|
@@ -1802,6 +1790,7 @@ function createSqliteDb(dbPath) {
|
|
|
1802
1790
|
db = new Database(path);
|
|
1803
1791
|
db.exec("PRAGMA journal_mode=WAL");
|
|
1804
1792
|
db.exec("PRAGMA synchronous=NORMAL");
|
|
1793
|
+
migrateRemovedAtColumn(db);
|
|
1805
1794
|
db.exec(SCHEMA);
|
|
1806
1795
|
db.exec(FTS_SCHEMA);
|
|
1807
1796
|
db.exec(SYNC_STATE_SCHEMA);
|
|
@@ -1897,6 +1886,15 @@ function insertStagingBatch(queue, jobs) {
|
|
|
1897
1886
|
});
|
|
1898
1887
|
insert(jobs);
|
|
1899
1888
|
}
|
|
1889
|
+
function findResurrectedIdsByStagingDiff(queue) {
|
|
1890
|
+
const database = getSqliteDb();
|
|
1891
|
+
const rows = database.prepare(`
|
|
1892
|
+
SELECT s.id FROM sync_staging s
|
|
1893
|
+
JOIN jobs j ON s.queue = j.queue AND s.id = j.id
|
|
1894
|
+
WHERE s.queue = ? AND j.removed_at IS NOT NULL
|
|
1895
|
+
`).all(queue);
|
|
1896
|
+
return rows.map((r) => r.id);
|
|
1897
|
+
}
|
|
1900
1898
|
function findNewIdsByStagingDiff(queue) {
|
|
1901
1899
|
const database = getSqliteDb();
|
|
1902
1900
|
return database.prepare(`
|
|
@@ -1910,7 +1908,7 @@ function findChangedIdsByStagingDiff(queue) {
|
|
|
1910
1908
|
return database.prepare(`
|
|
1911
1909
|
SELECT s.id, s.state FROM sync_staging s
|
|
1912
1910
|
JOIN jobs j ON s.queue = j.queue AND s.id = j.id
|
|
1913
|
-
WHERE s.queue = ? AND s.state != j.state
|
|
1911
|
+
WHERE s.queue = ? AND j.removed_at IS NULL AND s.state != j.state
|
|
1914
1912
|
`).all(queue);
|
|
1915
1913
|
}
|
|
1916
1914
|
function findStaleIdsByStagingDiff(queue) {
|
|
@@ -1918,11 +1916,11 @@ function findStaleIdsByStagingDiff(queue) {
|
|
|
1918
1916
|
const rows = database.prepare(`
|
|
1919
1917
|
SELECT j.id FROM jobs j
|
|
1920
1918
|
LEFT JOIN sync_staging s ON j.queue = s.queue AND j.id = s.id
|
|
1921
|
-
WHERE j.queue = ? AND s.id IS NULL
|
|
1919
|
+
WHERE j.queue = ? AND j.removed_at IS NULL AND s.id IS NULL
|
|
1922
1920
|
`).all(queue);
|
|
1923
1921
|
return rows.map((r) => r.id);
|
|
1924
1922
|
}
|
|
1925
|
-
function
|
|
1923
|
+
function softDeleteJobsByIds(queue, ids, now) {
|
|
1926
1924
|
if (ids.length === 0)
|
|
1927
1925
|
return 0;
|
|
1928
1926
|
const database = getSqliteDb();
|
|
@@ -1931,12 +1929,25 @@ function deleteJobsByIds(queue, ids) {
|
|
|
1931
1929
|
for (let i = 0;i < ids.length; i += BATCH_SIZE) {
|
|
1932
1930
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
1933
1931
|
const placeholders = batch.map(() => "?").join(",");
|
|
1934
|
-
database.prepare(`
|
|
1932
|
+
database.prepare(`UPDATE jobs SET removed_at = ? WHERE queue = ? AND id IN (${placeholders})`).run(now, queue, ...batch);
|
|
1935
1933
|
}
|
|
1936
1934
|
});
|
|
1937
1935
|
run();
|
|
1938
1936
|
return ids.length;
|
|
1939
1937
|
}
|
|
1938
|
+
function compactRemovedJobs(now, retentionMs) {
|
|
1939
|
+
const database = getSqliteDb();
|
|
1940
|
+
const cutoff = now - retentionMs;
|
|
1941
|
+
const filter = "removed_at IS NOT NULL AND removed_at < ?";
|
|
1942
|
+
const run = database.transaction(() => {
|
|
1943
|
+
const { n } = database.prepare(`SELECT COUNT(*) as n FROM jobs WHERE ${filter}`).get(cutoff);
|
|
1944
|
+
if (n > 0) {
|
|
1945
|
+
database.prepare(`DELETE FROM jobs WHERE ${filter}`).run(cutoff);
|
|
1946
|
+
}
|
|
1947
|
+
return n;
|
|
1948
|
+
});
|
|
1949
|
+
return run();
|
|
1950
|
+
}
|
|
1940
1951
|
function dropSyncStaging() {
|
|
1941
1952
|
const database = getSqliteDb();
|
|
1942
1953
|
database.exec("DROP TABLE IF EXISTS sync_staging");
|
|
@@ -1993,7 +2004,7 @@ async function syncQueue(queueName) {
|
|
|
1993
2004
|
return {
|
|
1994
2005
|
inserted: 0,
|
|
1995
2006
|
stateUpdated: 0,
|
|
1996
|
-
|
|
2007
|
+
softDeleted: 0,
|
|
1997
2008
|
total: 0,
|
|
1998
2009
|
error: message
|
|
1999
2010
|
};
|
|
@@ -2014,6 +2025,10 @@ async function syncQueue(queueName) {
|
|
|
2014
2025
|
total += batch.length;
|
|
2015
2026
|
}
|
|
2016
2027
|
assertSameConnection();
|
|
2028
|
+
const resurrected = findResurrectedIdsByStagingDiff(queueName);
|
|
2029
|
+
if (resurrected.length > 0) {
|
|
2030
|
+
throw new Error(`Resurrected job IDs detected in queue "${queueName}": ` + `${resurrected.join(", ")}. ` + `Soft-deleted IDs are not allowed to reappear in Redis.`);
|
|
2031
|
+
}
|
|
2017
2032
|
const newStubs = findNewIdsByStagingDiff(queueName);
|
|
2018
2033
|
if (newStubs.length > 0) {
|
|
2019
2034
|
upsertJobStubs(queueName, newStubs);
|
|
@@ -2023,15 +2038,16 @@ async function syncQueue(queueName) {
|
|
|
2023
2038
|
upsertJobStubs(queueName, changed);
|
|
2024
2039
|
}
|
|
2025
2040
|
const staleIds = findStaleIdsByStagingDiff(queueName).filter((id) => !wasPolledSince(queueName, id, syncStart));
|
|
2026
|
-
const
|
|
2041
|
+
const now = Date.now();
|
|
2042
|
+
const softDeleted = softDeleteJobsByIds(queueName, staleIds, now);
|
|
2027
2043
|
upsertSyncState(queueName, {
|
|
2028
2044
|
jobCount: total,
|
|
2029
|
-
syncedAt:
|
|
2045
|
+
syncedAt: now
|
|
2030
2046
|
});
|
|
2031
2047
|
return {
|
|
2032
2048
|
inserted: newStubs.length,
|
|
2033
2049
|
stateUpdated: changed.length,
|
|
2034
|
-
|
|
2050
|
+
softDeleted,
|
|
2035
2051
|
total
|
|
2036
2052
|
};
|
|
2037
2053
|
} catch (error) {
|
|
@@ -2040,7 +2056,7 @@ async function syncQueue(queueName) {
|
|
|
2040
2056
|
return {
|
|
2041
2057
|
inserted: 0,
|
|
2042
2058
|
stateUpdated: 0,
|
|
2043
|
-
|
|
2059
|
+
softDeleted: 0,
|
|
2044
2060
|
total: 0,
|
|
2045
2061
|
error: message
|
|
2046
2062
|
};
|
|
@@ -2065,12 +2081,13 @@ async function fullSync() {
|
|
|
2065
2081
|
return {
|
|
2066
2082
|
queues: 0,
|
|
2067
2083
|
totalInserted: 0,
|
|
2068
|
-
|
|
2084
|
+
totalSoftDeleted: 0,
|
|
2085
|
+
totalCompacted: 0,
|
|
2069
2086
|
errors: [{ queue: "", error: message }]
|
|
2070
2087
|
};
|
|
2071
2088
|
}
|
|
2072
2089
|
let totalInserted = 0;
|
|
2073
|
-
let
|
|
2090
|
+
let totalSoftDeleted = 0;
|
|
2074
2091
|
const errors = [];
|
|
2075
2092
|
for (const q of queues) {
|
|
2076
2093
|
const result = await syncQueue(q);
|
|
@@ -2078,10 +2095,17 @@ async function fullSync() {
|
|
|
2078
2095
|
errors.push({ queue: q, error: result.error });
|
|
2079
2096
|
} else {
|
|
2080
2097
|
totalInserted += result.inserted;
|
|
2081
|
-
|
|
2098
|
+
totalSoftDeleted += result.softDeleted;
|
|
2082
2099
|
}
|
|
2083
2100
|
}
|
|
2084
|
-
|
|
2101
|
+
const totalCompacted = compactRemovedJobs(Date.now(), getConfig().retentionMs);
|
|
2102
|
+
return {
|
|
2103
|
+
queues: queues.length,
|
|
2104
|
+
totalInserted,
|
|
2105
|
+
totalSoftDeleted,
|
|
2106
|
+
totalCompacted,
|
|
2107
|
+
errors
|
|
2108
|
+
};
|
|
2085
2109
|
}
|
|
2086
2110
|
|
|
2087
2111
|
// src/polling.ts
|
|
@@ -3824,12 +3848,6 @@ function formatTs(ts) {
|
|
|
3824
3848
|
return "-";
|
|
3825
3849
|
return new Date(ts).toISOString().replace("T", " ").slice(0, 19);
|
|
3826
3850
|
}
|
|
3827
|
-
function padRight(str, len) {
|
|
3828
|
-
return str.length >= len ? str : str + " ".repeat(len - str.length);
|
|
3829
|
-
}
|
|
3830
|
-
function padLeft(str, len) {
|
|
3831
|
-
return str.length >= len ? str : " ".repeat(len - str.length) + str;
|
|
3832
|
-
}
|
|
3833
3851
|
function table(headers, rows, align) {
|
|
3834
3852
|
const cols = headers.length;
|
|
3835
3853
|
const widths = headers.map((h) => h.length);
|
|
@@ -3838,7 +3856,10 @@ function table(headers, rows, align) {
|
|
|
3838
3856
|
widths[i] = Math.max(widths[i], (row[i] ?? "").length);
|
|
3839
3857
|
}
|
|
3840
3858
|
}
|
|
3841
|
-
const pad = (val, i) =>
|
|
3859
|
+
const pad = (val, i) => {
|
|
3860
|
+
const width = widths[i];
|
|
3861
|
+
return (align?.[i] ?? "l") === "r" ? val.padStart(width) : val.padEnd(width);
|
|
3862
|
+
};
|
|
3842
3863
|
const headerLine = headers.map(pad).join(" ");
|
|
3843
3864
|
const separator = widths.map((w) => "-".repeat(w)).join(" ");
|
|
3844
3865
|
const bodyLines = rows.map((row) => row.map((val, i) => pad(val, i)).join(" "));
|
|
@@ -4096,6 +4117,12 @@ function formatJobsRetry(r) {
|
|
|
4096
4117
|
|
|
4097
4118
|
// src/json-reporter.ts
|
|
4098
4119
|
import readline2 from "readline";
|
|
4120
|
+
function createResponse(data) {
|
|
4121
|
+
return {
|
|
4122
|
+
timestamp: new Date().toISOString(),
|
|
4123
|
+
...data
|
|
4124
|
+
};
|
|
4125
|
+
}
|
|
4099
4126
|
async function fetchQueuesOverview() {
|
|
4100
4127
|
const queueNames = await discoverQueueNames();
|
|
4101
4128
|
const queues = await Promise.all(queueNames.map((name) => getQueueStats(name)));
|
|
@@ -4107,25 +4134,23 @@ async function fetchQueuesOverview() {
|
|
|
4107
4134
|
delayed: acc.delayed + q.counts.delayed,
|
|
4108
4135
|
total: acc.total + q.total
|
|
4109
4136
|
}), { wait: 0, active: 0, completed: 0, failed: 0, delayed: 0, total: 0 });
|
|
4110
|
-
return {
|
|
4111
|
-
timestamp: new Date().toISOString(),
|
|
4137
|
+
return createResponse({
|
|
4112
4138
|
queues,
|
|
4113
4139
|
metrics: {
|
|
4114
4140
|
queueCount: queues.length,
|
|
4115
4141
|
jobCounts
|
|
4116
4142
|
}
|
|
4117
|
-
};
|
|
4143
|
+
});
|
|
4118
4144
|
}
|
|
4119
4145
|
async function fetchQueuesDelete(queueName, dryRun) {
|
|
4120
4146
|
const result = await deleteQueue(queueName, dryRun);
|
|
4121
|
-
return {
|
|
4122
|
-
timestamp: new Date().toISOString(),
|
|
4147
|
+
return createResponse({
|
|
4123
4148
|
queue: queueName,
|
|
4124
4149
|
deleted: !dryRun,
|
|
4125
4150
|
dryRun,
|
|
4126
4151
|
jobCounts: result.counts,
|
|
4127
4152
|
totalJobs: result.counts.wait + result.counts.active + result.counts.completed + result.counts.failed + result.counts.delayed
|
|
4128
|
-
};
|
|
4153
|
+
});
|
|
4129
4154
|
}
|
|
4130
4155
|
async function fetchJobsList(queueName, jobState, maxResults) {
|
|
4131
4156
|
const { jobs, total } = await getAllJobs(queueName, jobState, maxResults, true);
|
|
@@ -4139,13 +4164,12 @@ async function fetchJobsList(queueName, jobState, maxResults) {
|
|
|
4139
4164
|
})));
|
|
4140
4165
|
markPolledWrites(queueName, jobs.map((j) => j.id));
|
|
4141
4166
|
} catch {}
|
|
4142
|
-
return {
|
|
4143
|
-
timestamp: new Date().toISOString(),
|
|
4167
|
+
return createResponse({
|
|
4144
4168
|
queue: queueName,
|
|
4145
4169
|
jobState: jobState ?? "all",
|
|
4146
4170
|
jobs,
|
|
4147
4171
|
total
|
|
4148
|
-
};
|
|
4172
|
+
});
|
|
4149
4173
|
}
|
|
4150
4174
|
function computeRetryExitCode(result) {
|
|
4151
4175
|
if (!result.dryRun && result.errors.length > 0)
|
|
@@ -4159,8 +4183,7 @@ async function fetchJobsRetry(queueName, jobState, since, name, pageSize, dryRun
|
|
|
4159
4183
|
filter.since = since;
|
|
4160
4184
|
if (name !== undefined)
|
|
4161
4185
|
filter.name = name;
|
|
4162
|
-
return {
|
|
4163
|
-
timestamp: new Date().toISOString(),
|
|
4186
|
+
return createResponse({
|
|
4164
4187
|
command: "jobs-retry",
|
|
4165
4188
|
dryRun,
|
|
4166
4189
|
queue: queueName,
|
|
@@ -4171,7 +4194,7 @@ async function fetchJobsRetry(queueName, jobState, since, name, pageSize, dryRun
|
|
|
4171
4194
|
sampleJobIds: result.sampleJobIds,
|
|
4172
4195
|
totalFailed: result.totalFailed,
|
|
4173
4196
|
truncated: result.truncated
|
|
4174
|
-
};
|
|
4197
|
+
});
|
|
4175
4198
|
}
|
|
4176
4199
|
async function fetchJobDetail(queueName, jobId) {
|
|
4177
4200
|
const job = await getJobDetail(queueName, jobId);
|
|
@@ -4182,20 +4205,18 @@ async function fetchJobDetail(queueName, jobId) {
|
|
|
4182
4205
|
} catch {}
|
|
4183
4206
|
process.exit(1);
|
|
4184
4207
|
}
|
|
4185
|
-
return {
|
|
4186
|
-
timestamp: new Date().toISOString(),
|
|
4208
|
+
return createResponse({
|
|
4187
4209
|
queue: queueName,
|
|
4188
4210
|
job
|
|
4189
|
-
};
|
|
4211
|
+
});
|
|
4190
4212
|
}
|
|
4191
4213
|
async function fetchSchedulersList(queueName, maxResults) {
|
|
4192
4214
|
const { schedulers, total } = await getAllJobSchedulers(queueName, maxResults);
|
|
4193
|
-
return {
|
|
4194
|
-
timestamp: new Date().toISOString(),
|
|
4215
|
+
return createResponse({
|
|
4195
4216
|
queue: queueName,
|
|
4196
4217
|
schedulers,
|
|
4197
4218
|
total
|
|
4198
|
-
};
|
|
4219
|
+
});
|
|
4199
4220
|
}
|
|
4200
4221
|
async function fetchSchedulerDetail(queueName, schedulerKey) {
|
|
4201
4222
|
const scheduler = await getJobSchedulerDetail(queueName, schedulerKey);
|
|
@@ -4206,11 +4227,10 @@ async function fetchSchedulerDetail(queueName, schedulerKey) {
|
|
|
4206
4227
|
} catch {}
|
|
4207
4228
|
process.exit(1);
|
|
4208
4229
|
}
|
|
4209
|
-
return {
|
|
4210
|
-
timestamp: new Date().toISOString(),
|
|
4230
|
+
return createResponse({
|
|
4211
4231
|
queue: queueName,
|
|
4212
4232
|
scheduler
|
|
4213
|
-
};
|
|
4233
|
+
});
|
|
4214
4234
|
}
|
|
4215
4235
|
function validateJobState(jobState) {
|
|
4216
4236
|
if (!jobState)
|
|
@@ -4382,5 +4402,5 @@ async function main() {
|
|
|
4382
4402
|
}
|
|
4383
4403
|
main();
|
|
4384
4404
|
|
|
4385
|
-
//# debugId=
|
|
4405
|
+
//# debugId=ABA0BC9822B1617064756E2164756E21
|
|
4386
4406
|
//# sourceMappingURL=index.js.map
|