nvent 0.4.4 → 0.5.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/module.d.mts +4 -185
- package/dist/module.json +3 -3
- package/dist/module.mjs +451 -257
- package/dist/runtime/adapters/base/index.d.ts +6 -0
- package/dist/runtime/adapters/base/index.js +1 -0
- package/dist/runtime/adapters/base/store-validator.d.ts +48 -0
- package/dist/runtime/adapters/base/store-validator.js +147 -0
- package/dist/runtime/adapters/builtin/file-queue.d.ts +67 -0
- package/dist/runtime/adapters/builtin/file-queue.js +499 -0
- package/dist/runtime/adapters/builtin/file-store.d.ts +32 -0
- package/dist/runtime/adapters/builtin/file-store.js +206 -0
- package/dist/runtime/adapters/builtin/file-stream.d.ts +39 -0
- package/dist/runtime/adapters/builtin/file-stream.js +56 -0
- package/dist/runtime/adapters/builtin/index.d.ts +10 -0
- package/dist/runtime/adapters/builtin/index.js +5 -0
- package/dist/runtime/adapters/builtin/memory-queue.d.ts +52 -0
- package/dist/runtime/adapters/builtin/memory-queue.js +243 -0
- package/dist/runtime/adapters/builtin/memory-store.d.ts +68 -0
- package/dist/runtime/adapters/builtin/memory-store.js +333 -0
- package/dist/runtime/adapters/builtin/memory-stream.d.ts +21 -0
- package/dist/runtime/adapters/builtin/memory-stream.js +56 -0
- package/dist/runtime/adapters/factory.d.ts +31 -0
- package/dist/runtime/adapters/factory.js +134 -0
- package/dist/runtime/adapters/index.d.ts +8 -0
- package/dist/runtime/adapters/index.js +3 -0
- package/dist/runtime/adapters/interfaces/index.d.ts +11 -0
- package/dist/runtime/adapters/interfaces/index.js +3 -0
- package/dist/runtime/adapters/interfaces/queue.d.ts +150 -0
- package/dist/runtime/adapters/interfaces/store.d.ts +297 -0
- package/dist/runtime/adapters/interfaces/stream.d.ts +62 -0
- package/dist/runtime/adapters/registry.d.ts +85 -0
- package/dist/runtime/adapters/registry.js +161 -0
- package/dist/runtime/config/index.d.ts +29 -0
- package/dist/runtime/config/index.js +175 -0
- package/dist/runtime/config/types.d.ts +397 -0
- package/dist/runtime/config/types.js +0 -0
- package/dist/runtime/{server-utils/events → events}/eventBus.d.ts +1 -1
- package/dist/runtime/events/types.d.ts +145 -0
- package/dist/runtime/events/types.js +0 -0
- package/dist/runtime/events/utils/scheduleTrigger.d.ts +8 -0
- package/dist/runtime/events/utils/scheduleTrigger.js +69 -0
- package/dist/runtime/events/utils/stallDetector.d.ts +140 -0
- package/dist/runtime/events/utils/stallDetector.js +436 -0
- package/dist/runtime/events/utils/triggerRuntime.d.ts +58 -0
- package/dist/runtime/events/utils/triggerRuntime.js +212 -0
- package/dist/runtime/{server-utils/events → events}/wiring/flowWiring.d.ts +12 -11
- package/dist/runtime/events/wiring/flowWiring.js +1020 -0
- package/dist/runtime/events/wiring/registry.d.ts +19 -0
- package/dist/runtime/events/wiring/registry.js +35 -0
- package/dist/runtime/events/wiring/stateWiring.d.ts +37 -0
- package/dist/runtime/events/wiring/stateWiring.js +92 -0
- package/dist/runtime/events/wiring/streamWiring.d.ts +36 -0
- package/dist/runtime/events/wiring/streamWiring.js +156 -0
- package/dist/runtime/events/wiring/triggerWiring.d.ts +21 -0
- package/dist/runtime/events/wiring/triggerWiring.js +412 -0
- package/dist/runtime/nitro/plugins/00.adapters.d.ts +14 -0
- package/dist/runtime/nitro/plugins/00.adapters.js +73 -0
- package/dist/runtime/nitro/plugins/02.workers.js +63 -0
- package/dist/runtime/nitro/plugins/03.triggers.d.ts +12 -0
- package/dist/runtime/nitro/plugins/03.triggers.js +55 -0
- package/dist/runtime/nitro/routes/webhook.await.d.ts +23 -0
- package/dist/runtime/nitro/routes/webhook.await.js +90 -0
- package/dist/runtime/nitro/routes/webhook.trigger.d.ts +69 -0
- package/dist/runtime/nitro/routes/webhook.trigger.js +64 -0
- package/dist/runtime/nitro/utils/adapters.d.ts +66 -0
- package/dist/runtime/nitro/utils/adapters.js +51 -0
- package/dist/runtime/nitro/utils/awaitPatterns/event.d.ts +15 -0
- package/dist/runtime/nitro/utils/awaitPatterns/event.js +120 -0
- package/dist/runtime/nitro/utils/awaitPatterns/index.d.ts +28 -0
- package/dist/runtime/nitro/utils/awaitPatterns/index.js +55 -0
- package/dist/runtime/nitro/utils/awaitPatterns/schedule.d.ts +16 -0
- package/dist/runtime/nitro/utils/awaitPatterns/schedule.js +78 -0
- package/dist/runtime/nitro/utils/awaitPatterns/time.d.ts +15 -0
- package/dist/runtime/nitro/utils/awaitPatterns/time.js +67 -0
- package/dist/runtime/nitro/utils/awaitPatterns/webhook.d.ts +15 -0
- package/dist/runtime/nitro/utils/awaitPatterns/webhook.js +120 -0
- package/dist/runtime/nitro/utils/defineFunction.d.ts +10 -0
- package/dist/runtime/nitro/utils/defineFunction.js +17 -0
- package/dist/runtime/nitro/utils/defineFunctionConfig.d.ts +310 -0
- package/dist/runtime/nitro/utils/defineFunctionConfig.js +3 -0
- package/dist/runtime/nitro/utils/defineHooks.d.ts +41 -0
- package/dist/runtime/nitro/utils/defineHooks.js +6 -0
- package/dist/runtime/nitro/utils/registerAdapter.d.ts +59 -0
- package/dist/runtime/nitro/utils/registerAdapter.js +13 -0
- package/dist/runtime/nitro/utils/useAwait.d.ts +71 -0
- package/dist/runtime/nitro/utils/useAwait.js +139 -0
- package/dist/runtime/{server-utils → nitro}/utils/useEventManager.d.ts +2 -2
- package/dist/runtime/{server-utils → nitro}/utils/useEventManager.js +1 -1
- package/dist/runtime/nitro/utils/useFlow.d.ts +68 -0
- package/dist/runtime/nitro/utils/useFlow.js +226 -0
- package/dist/runtime/nitro/utils/useHookRegistry.d.ts +34 -0
- package/dist/runtime/nitro/utils/useHookRegistry.js +25 -0
- package/dist/runtime/{server-utils → nitro}/utils/useNventLogger.js +2 -2
- package/dist/runtime/nitro/utils/useRunContext.d.ts +6 -0
- package/dist/runtime/nitro/utils/useRunContext.js +102 -0
- package/dist/runtime/nitro/utils/useStreamTopics.d.ts +83 -0
- package/dist/runtime/nitro/utils/useStreamTopics.js +94 -0
- package/dist/runtime/nitro/utils/useTrigger.d.ts +150 -0
- package/dist/runtime/nitro/utils/useTrigger.js +320 -0
- package/dist/runtime/scheduler/index.d.ts +33 -0
- package/dist/runtime/scheduler/index.js +38 -0
- package/dist/runtime/scheduler/scheduler.d.ts +113 -0
- package/dist/runtime/scheduler/scheduler.js +623 -0
- package/dist/runtime/scheduler/types.d.ts +116 -0
- package/dist/runtime/scheduler/types.js +0 -0
- package/dist/runtime/tsconfig.json +8 -0
- package/dist/runtime/worker/node/runner.d.ts +53 -0
- package/dist/runtime/worker/node/runner.js +327 -0
- package/dist/types.d.mts +2 -2
- package/package.json +16 -46
- package/LICENSE +0 -21
- package/README.md +0 -389
- package/dist/runtime/app/assets/vueflow.css +0 -1
- package/dist/runtime/app/components/ConfirmDialog.d.vue.ts +0 -33
- package/dist/runtime/app/components/ConfirmDialog.vue +0 -121
- package/dist/runtime/app/components/ConfirmDialog.vue.d.ts +0 -33
- package/dist/runtime/app/components/FlowDiagram.d.vue.ts +0 -64
- package/dist/runtime/app/components/FlowDiagram.vue +0 -338
- package/dist/runtime/app/components/FlowDiagram.vue.d.ts +0 -64
- package/dist/runtime/app/components/FlowNodeCard.d.vue.ts +0 -29
- package/dist/runtime/app/components/FlowNodeCard.vue +0 -156
- package/dist/runtime/app/components/FlowNodeCard.vue.d.ts +0 -29
- package/dist/runtime/app/components/FlowRunOverview.d.vue.ts +0 -9
- package/dist/runtime/app/components/FlowRunOverview.vue +0 -291
- package/dist/runtime/app/components/FlowRunOverview.vue.d.ts +0 -9
- package/dist/runtime/app/components/FlowRunStatusBadge.d.vue.ts +0 -14
- package/dist/runtime/app/components/FlowRunStatusBadge.vue +0 -60
- package/dist/runtime/app/components/FlowRunStatusBadge.vue.d.ts +0 -14
- package/dist/runtime/app/components/FlowRunTimeline.d.vue.ts +0 -12
- package/dist/runtime/app/components/FlowRunTimeline.vue +0 -127
- package/dist/runtime/app/components/FlowRunTimeline.vue.d.ts +0 -12
- package/dist/runtime/app/components/FlowScheduleDialog.d.vue.ts +0 -16
- package/dist/runtime/app/components/FlowScheduleDialog.vue +0 -226
- package/dist/runtime/app/components/FlowScheduleDialog.vue.d.ts +0 -16
- package/dist/runtime/app/components/FlowSchedulesList.d.vue.ts +0 -12
- package/dist/runtime/app/components/FlowSchedulesList.vue +0 -99
- package/dist/runtime/app/components/FlowSchedulesList.vue.d.ts +0 -12
- package/dist/runtime/app/components/JobScheduling.d.vue.ts +0 -6
- package/dist/runtime/app/components/JobScheduling.vue +0 -203
- package/dist/runtime/app/components/JobScheduling.vue.d.ts +0 -6
- package/dist/runtime/app/components/ListItem.d.vue.ts +0 -23
- package/dist/runtime/app/components/ListItem.vue +0 -70
- package/dist/runtime/app/components/ListItem.vue.d.ts +0 -23
- package/dist/runtime/app/components/QueueConfigDetails.d.vue.ts +0 -45
- package/dist/runtime/app/components/QueueConfigDetails.vue +0 -412
- package/dist/runtime/app/components/QueueConfigDetails.vue.d.ts +0 -45
- package/dist/runtime/app/components/StatCounter.d.vue.ts +0 -9
- package/dist/runtime/app/components/StatCounter.vue +0 -25
- package/dist/runtime/app/components/StatCounter.vue.d.ts +0 -9
- package/dist/runtime/app/components/TimelineList.d.vue.ts +0 -7
- package/dist/runtime/app/components/TimelineList.vue +0 -210
- package/dist/runtime/app/components/TimelineList.vue.d.ts +0 -7
- package/dist/runtime/app/components/nhealth/component-router.d.vue.ts +0 -46
- package/dist/runtime/app/components/nhealth/component-router.vue +0 -26
- package/dist/runtime/app/components/nhealth/component-router.vue.d.ts +0 -46
- package/dist/runtime/app/components/nhealth/component-shell.d.vue.ts +0 -24
- package/dist/runtime/app/components/nhealth/component-shell.vue +0 -89
- package/dist/runtime/app/components/nhealth/component-shell.vue.d.ts +0 -24
- package/dist/runtime/app/composables/useAnalyzedFlows.d.ts +0 -14
- package/dist/runtime/app/composables/useAnalyzedFlows.js +0 -8
- package/dist/runtime/app/composables/useComponentRouter.d.ts +0 -38
- package/dist/runtime/app/composables/useComponentRouter.js +0 -240
- package/dist/runtime/app/composables/useFlowRunTimeline.d.ts +0 -80
- package/dist/runtime/app/composables/useFlowRunTimeline.js +0 -68
- package/dist/runtime/app/composables/useFlowRuns.d.ts +0 -18
- package/dist/runtime/app/composables/useFlowRuns.js +0 -32
- package/dist/runtime/app/composables/useFlowRunsInfinite.d.ts +0 -24
- package/dist/runtime/app/composables/useFlowRunsInfinite.js +0 -123
- package/dist/runtime/app/composables/useFlowRunsPolling.d.ts +0 -9
- package/dist/runtime/app/composables/useFlowRunsPolling.js +0 -33
- package/dist/runtime/app/composables/useFlowState.d.ts +0 -125
- package/dist/runtime/app/composables/useFlowState.js +0 -211
- package/dist/runtime/app/composables/useFlowWebSocket.d.ts +0 -27
- package/dist/runtime/app/composables/useFlowWebSocket.js +0 -205
- package/dist/runtime/app/composables/useFlowsNavigation.d.ts +0 -10
- package/dist/runtime/app/composables/useFlowsNavigation.js +0 -58
- package/dist/runtime/app/composables/useQueueJobs.d.ts +0 -26
- package/dist/runtime/app/composables/useQueueJobs.js +0 -20
- package/dist/runtime/app/composables/useQueueUpdates.d.ts +0 -26
- package/dist/runtime/app/composables/useQueueUpdates.js +0 -122
- package/dist/runtime/app/composables/useQueues.d.ts +0 -45
- package/dist/runtime/app/composables/useQueues.js +0 -26
- package/dist/runtime/app/composables/useQueuesLive.d.ts +0 -19
- package/dist/runtime/app/composables/useQueuesLive.js +0 -143
- package/dist/runtime/app/pages/flows/index.d.vue.ts +0 -3
- package/dist/runtime/app/pages/flows/index.vue +0 -645
- package/dist/runtime/app/pages/flows/index.vue.d.ts +0 -3
- package/dist/runtime/app/pages/index.d.vue.ts +0 -3
- package/dist/runtime/app/pages/index.vue +0 -34
- package/dist/runtime/app/pages/index.vue.d.ts +0 -3
- package/dist/runtime/app/pages/queues/index.d.vue.ts +0 -3
- package/dist/runtime/app/pages/queues/index.vue +0 -229
- package/dist/runtime/app/pages/queues/index.vue.d.ts +0 -3
- package/dist/runtime/app/pages/queues/job.d.vue.ts +0 -3
- package/dist/runtime/app/pages/queues/job.vue +0 -262
- package/dist/runtime/app/pages/queues/job.vue.d.ts +0 -3
- package/dist/runtime/app/pages/queues/jobs.d.vue.ts +0 -3
- package/dist/runtime/app/pages/queues/jobs.vue +0 -291
- package/dist/runtime/app/pages/queues/jobs.vue.d.ts +0 -3
- package/dist/runtime/app/plugins/vueflow.client.d.ts +0 -2
- package/dist/runtime/app/plugins/vueflow.client.js +0 -11
- package/dist/runtime/constants.d.ts +0 -11
- package/dist/runtime/constants.js +0 -11
- package/dist/runtime/schema.d.ts +0 -37
- package/dist/runtime/schema.js +0 -20
- package/dist/runtime/server/api/_flows/[name]/clear-history.delete.d.ts +0 -10
- package/dist/runtime/server/api/_flows/[name]/clear-history.delete.js +0 -44
- package/dist/runtime/server/api/_flows/[name]/runs.get.d.ts +0 -7
- package/dist/runtime/server/api/_flows/[name]/runs.get.js +0 -53
- package/dist/runtime/server/api/_flows/[name]/schedule.post.js +0 -57
- package/dist/runtime/server/api/_flows/[name]/schedules/[id].delete.d.ts +0 -2
- package/dist/runtime/server/api/_flows/[name]/schedules/[id].delete.js +0 -42
- package/dist/runtime/server/api/_flows/[name]/schedules.get.d.ts +0 -2
- package/dist/runtime/server/api/_flows/[name]/schedules.get.js +0 -48
- package/dist/runtime/server/api/_flows/[name]/start.post.d.ts +0 -2
- package/dist/runtime/server/api/_flows/[name]/start.post.js +0 -9
- package/dist/runtime/server/api/_flows/index.get.d.ts +0 -6
- package/dist/runtime/server/api/_flows/index.get.js +0 -5
- package/dist/runtime/server/api/_flows/ws.d.ts +0 -60
- package/dist/runtime/server/api/_flows/ws.js +0 -188
- package/dist/runtime/server/api/_queues/[name]/job/[id].get.d.ts +0 -2
- package/dist/runtime/server/api/_queues/[name]/job/[id].get.js +0 -9
- package/dist/runtime/server/api/_queues/[name]/job/index.get.d.ts +0 -2
- package/dist/runtime/server/api/_queues/[name]/job/index.get.js +0 -18
- package/dist/runtime/server/api/_queues/index.get.d.ts +0 -2
- package/dist/runtime/server/api/_queues/index.get.js +0 -63
- package/dist/runtime/server/api/_queues/ws.d.ts +0 -48
- package/dist/runtime/server/api/_queues/ws.js +0 -205
- package/dist/runtime/server/plugins/00.event-store.d.ts +0 -13
- package/dist/runtime/server/plugins/00.event-store.js +0 -16
- package/dist/runtime/server/plugins/flow-management.d.ts +0 -13
- package/dist/runtime/server/plugins/flow-management.js +0 -65
- package/dist/runtime/server/plugins/queue-management.d.ts +0 -2
- package/dist/runtime/server/plugins/queue-management.js +0 -27
- package/dist/runtime/server/plugins/state-cleanup.d.ts +0 -11
- package/dist/runtime/server/plugins/state-cleanup.js +0 -93
- package/dist/runtime/server/plugins/worker-management.d.ts +0 -2
- package/dist/runtime/server/plugins/worker-management.js +0 -33
- package/dist/runtime/server/tsconfig.json +0 -3
- package/dist/runtime/server-utils/events/adapters/fileAdapter.d.ts +0 -2
- package/dist/runtime/server-utils/events/adapters/fileAdapter.js +0 -382
- package/dist/runtime/server-utils/events/adapters/memoryAdapter.d.ts +0 -2
- package/dist/runtime/server-utils/events/adapters/memoryAdapter.js +0 -171
- package/dist/runtime/server-utils/events/adapters/redis/redisAdapter.d.ts +0 -2
- package/dist/runtime/server-utils/events/adapters/redis/redisAdapter.js +0 -348
- package/dist/runtime/server-utils/events/adapters/redis/redisPubSubGateway.d.ts +0 -30
- package/dist/runtime/server-utils/events/adapters/redis/redisPubSubGateway.js +0 -82
- package/dist/runtime/server-utils/events/eventStoreFactory.d.ts +0 -19
- package/dist/runtime/server-utils/events/eventStoreFactory.js +0 -44
- package/dist/runtime/server-utils/events/streamNames.d.ts +0 -17
- package/dist/runtime/server-utils/events/streamNames.js +0 -17
- package/dist/runtime/server-utils/events/types.d.ts +0 -63
- package/dist/runtime/server-utils/events/wiring/flowWiring.js +0 -409
- package/dist/runtime/server-utils/events/wiring/registry.d.ts +0 -10
- package/dist/runtime/server-utils/events/wiring/registry.js +0 -24
- package/dist/runtime/server-utils/queue/adapters/bullmq.d.ts +0 -18
- package/dist/runtime/server-utils/queue/adapters/bullmq.js +0 -164
- package/dist/runtime/server-utils/queue/queueFactory.d.ts +0 -3
- package/dist/runtime/server-utils/queue/queueFactory.js +0 -10
- package/dist/runtime/server-utils/queue/types.d.ts +0 -47
- package/dist/runtime/server-utils/state/adapters/redis.d.ts +0 -2
- package/dist/runtime/server-utils/state/adapters/redis.js +0 -42
- package/dist/runtime/server-utils/state/stateFactory.d.ts +0 -3
- package/dist/runtime/server-utils/state/stateFactory.js +0 -17
- package/dist/runtime/server-utils/state/types.d.ts +0 -23
- package/dist/runtime/server-utils/utils/defineQueueConfig.d.ts +0 -154
- package/dist/runtime/server-utils/utils/defineQueueConfig.js +0 -2
- package/dist/runtime/server-utils/utils/defineQueueWorker.d.ts +0 -10
- package/dist/runtime/server-utils/utils/defineQueueWorker.js +0 -17
- package/dist/runtime/server-utils/utils/useEventStore.d.ts +0 -20
- package/dist/runtime/server-utils/utils/useEventStore.js +0 -119
- package/dist/runtime/server-utils/utils/useFlowEngine.d.ts +0 -9
- package/dist/runtime/server-utils/utils/useFlowEngine.js +0 -44
- package/dist/runtime/server-utils/utils/useLogs.d.ts +0 -41
- package/dist/runtime/server-utils/utils/useLogs.js +0 -74
- package/dist/runtime/server-utils/utils/useQueue.d.ts +0 -31
- package/dist/runtime/server-utils/utils/useQueue.js +0 -24
- package/dist/runtime/server-utils/worker/adapter.d.ts +0 -4
- package/dist/runtime/server-utils/worker/adapter.js +0 -66
- package/dist/runtime/server-utils/worker/runner/node.d.ts +0 -27
- package/dist/runtime/server-utils/worker/runner/node.js +0 -196
- package/dist/runtime/types.d.ts +0 -132
- /package/dist/runtime/{server-utils/events/types.js → adapters/interfaces/queue.js} +0 -0
- /package/dist/runtime/{server-utils/queue/types.js → adapters/interfaces/store.js} +0 -0
- /package/dist/runtime/{server-utils/state/types.js → adapters/interfaces/stream.js} +0 -0
- /package/dist/runtime/{server-utils/events → events}/eventBus.js +0 -0
- /package/dist/runtime/{server/plugins/00.ws-lifecycle.d.ts → nitro/plugins/01.ws-lifecycle.d.ts} +0 -0
- /package/dist/runtime/{server/plugins/00.ws-lifecycle.js → nitro/plugins/01.ws-lifecycle.js} +0 -0
- /package/dist/runtime/{server/api/_flows/[name]/schedule.post.d.ts → nitro/plugins/02.workers.d.ts} +0 -0
- /package/dist/runtime/{server-utils → nitro}/utils/useNventLogger.d.ts +0 -0
- /package/dist/runtime/{server-utils → nitro}/utils/wsPeerManager.d.ts +0 -0
- /package/dist/runtime/{server-utils → nitro}/utils/wsPeerManager.js +0 -0
- /package/dist/runtime/{python → worker/python}/get_config.py +0 -0
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import * as fastq from "fastq";
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import cronParser from "cron-parser";
|
|
5
|
+
export class FileQueueAdapter {
|
|
6
|
+
jobs = /* @__PURE__ */ new Map();
|
|
7
|
+
eventListeners = /* @__PURE__ */ new Map();
|
|
8
|
+
workers = /* @__PURE__ */ new Map();
|
|
9
|
+
scheduledJobs = /* @__PURE__ */ new Map();
|
|
10
|
+
options;
|
|
11
|
+
initialized = false;
|
|
12
|
+
constructor(options) {
|
|
13
|
+
this.options = {
|
|
14
|
+
dataDir: options.dataDir,
|
|
15
|
+
maxQueueSize: options.maxQueueSize || 1e4
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
async init() {
|
|
19
|
+
if (this.initialized) return;
|
|
20
|
+
await fs.mkdir(this.options.dataDir, { recursive: true });
|
|
21
|
+
await this.loadJobsFromDisk();
|
|
22
|
+
this.initialized = true;
|
|
23
|
+
}
|
|
24
|
+
async loadJobsFromDisk() {
|
|
25
|
+
const queuesDir = this.options.dataDir;
|
|
26
|
+
try {
|
|
27
|
+
const queueNames = await fs.readdir(queuesDir);
|
|
28
|
+
for (const queueName of queueNames) {
|
|
29
|
+
const jobsDir = join(queuesDir, queueName, "jobs");
|
|
30
|
+
try {
|
|
31
|
+
const jobFiles = await fs.readdir(jobsDir);
|
|
32
|
+
for (const jobFile of jobFiles) {
|
|
33
|
+
if (!jobFile.endsWith(".json")) continue;
|
|
34
|
+
const jobPath = join(jobsDir, jobFile);
|
|
35
|
+
const jobData = await fs.readFile(jobPath, "utf-8");
|
|
36
|
+
const job = JSON.parse(jobData);
|
|
37
|
+
this.jobs.set(job.id, job);
|
|
38
|
+
}
|
|
39
|
+
} catch {
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
} catch {
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async persistJob(queueName, job) {
|
|
46
|
+
const jobsDir = join(this.options.dataDir, queueName, "jobs");
|
|
47
|
+
await fs.mkdir(jobsDir, { recursive: true });
|
|
48
|
+
const jobPath = join(jobsDir, `${job.id}.json`);
|
|
49
|
+
await fs.writeFile(jobPath, JSON.stringify(job, null, 2));
|
|
50
|
+
}
|
|
51
|
+
async deleteJobFile(queueName, jobId) {
|
|
52
|
+
const jobPath = join(this.options.dataDir, queueName, "jobs", `${jobId}.json`);
|
|
53
|
+
try {
|
|
54
|
+
await fs.unlink(jobPath);
|
|
55
|
+
} catch {
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async enqueue(queueName, job) {
|
|
59
|
+
const jobId = job.opts?.jobId || this.generateId();
|
|
60
|
+
if (this.jobs.has(jobId)) {
|
|
61
|
+
return jobId;
|
|
62
|
+
}
|
|
63
|
+
if (this.jobs.size >= this.options.maxQueueSize) {
|
|
64
|
+
throw new Error(`Queue ${queueName} is full (max: ${this.options.maxQueueSize})`);
|
|
65
|
+
}
|
|
66
|
+
const internalJob = {
|
|
67
|
+
id: jobId,
|
|
68
|
+
name: job.name,
|
|
69
|
+
data: { ...job.data, __queueName: queueName },
|
|
70
|
+
state: "waiting",
|
|
71
|
+
timestamp: Date.now(),
|
|
72
|
+
attemptsMade: 0,
|
|
73
|
+
opts: job.opts
|
|
74
|
+
// Store job options for retry logic
|
|
75
|
+
};
|
|
76
|
+
this.jobs.set(jobId, internalJob);
|
|
77
|
+
await this.persistJob(queueName, internalJob);
|
|
78
|
+
this.emitEvent(queueName, "waiting", { jobId, job: internalJob });
|
|
79
|
+
const workerInfo = this.workers.get(queueName);
|
|
80
|
+
if (workerInfo && !workerInfo.paused) {
|
|
81
|
+
workerInfo.queue.push({ jobId, jobName: job.name, data: internalJob.data }).catch(() => {
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return jobId;
|
|
85
|
+
}
|
|
86
|
+
async schedule(queueName, job, opts) {
|
|
87
|
+
if (opts?.delay) {
|
|
88
|
+
const jobId = this.generateId();
|
|
89
|
+
const internalJob = {
|
|
90
|
+
id: jobId,
|
|
91
|
+
name: job.name,
|
|
92
|
+
data: { ...job.data, __queueName: queueName },
|
|
93
|
+
state: "delayed",
|
|
94
|
+
timestamp: Date.now()
|
|
95
|
+
};
|
|
96
|
+
this.jobs.set(jobId, internalJob);
|
|
97
|
+
await this.persistJob(queueName, internalJob);
|
|
98
|
+
this.emitEvent(queueName, "delayed", { jobId, job: internalJob, delay: opts.delay });
|
|
99
|
+
setTimeout(() => {
|
|
100
|
+
this.enqueue(queueName, job);
|
|
101
|
+
}, opts.delay);
|
|
102
|
+
return jobId;
|
|
103
|
+
}
|
|
104
|
+
if (opts?.cron || opts?.repeat) {
|
|
105
|
+
const scheduleId = this.generateId();
|
|
106
|
+
const cronPattern = opts.cron || opts.repeat?.pattern;
|
|
107
|
+
if (!cronPattern) {
|
|
108
|
+
throw new Error("Cron pattern is required for scheduled jobs");
|
|
109
|
+
}
|
|
110
|
+
const scheduledJob = {
|
|
111
|
+
queueName,
|
|
112
|
+
job,
|
|
113
|
+
opts,
|
|
114
|
+
repeatCount: 0
|
|
115
|
+
};
|
|
116
|
+
this.scheduledJobs.set(scheduleId, scheduledJob);
|
|
117
|
+
this.scheduleCronJob(scheduleId, scheduledJob);
|
|
118
|
+
console.info(`[FileQueue] Scheduled job "${job.name}" with cron pattern "${cronPattern}" (id: ${scheduleId})`);
|
|
119
|
+
return scheduleId;
|
|
120
|
+
}
|
|
121
|
+
return this.enqueue(queueName, job);
|
|
122
|
+
}
|
|
123
|
+
async getJob(_queueName, id) {
|
|
124
|
+
return this.jobs.get(id) || null;
|
|
125
|
+
}
|
|
126
|
+
async getJobs(queueName, query) {
|
|
127
|
+
let jobs = Array.from(this.jobs.values()).filter((j) => j.data?.__queueName === queueName);
|
|
128
|
+
if (query?.state && query.state.length > 0) {
|
|
129
|
+
jobs = jobs.filter((j) => query.state.includes(j.state));
|
|
130
|
+
}
|
|
131
|
+
if (query?.offset) {
|
|
132
|
+
jobs = jobs.slice(query.offset);
|
|
133
|
+
}
|
|
134
|
+
if (query?.limit) {
|
|
135
|
+
jobs = jobs.slice(0, query.limit);
|
|
136
|
+
}
|
|
137
|
+
return jobs;
|
|
138
|
+
}
|
|
139
|
+
on(queueName, event, callback) {
|
|
140
|
+
const key = `${queueName}:${event}`;
|
|
141
|
+
if (!this.eventListeners.has(key)) {
|
|
142
|
+
this.eventListeners.set(key, []);
|
|
143
|
+
}
|
|
144
|
+
this.eventListeners.get(key).push(callback);
|
|
145
|
+
return () => {
|
|
146
|
+
const listeners = this.eventListeners.get(key);
|
|
147
|
+
if (listeners) {
|
|
148
|
+
const index = listeners.indexOf(callback);
|
|
149
|
+
if (index > -1) {
|
|
150
|
+
listeners.splice(index, 1);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
async isPaused(queueName) {
|
|
156
|
+
const workerInfo = this.workers.get(queueName);
|
|
157
|
+
return workerInfo?.paused || false;
|
|
158
|
+
}
|
|
159
|
+
async getJobCounts(queueName) {
|
|
160
|
+
const jobs = Array.from(this.jobs.values()).filter((j) => j.data?.__queueName === queueName);
|
|
161
|
+
return {
|
|
162
|
+
active: jobs.filter((j) => j.state === "active").length,
|
|
163
|
+
completed: jobs.filter((j) => j.state === "completed").length,
|
|
164
|
+
failed: jobs.filter((j) => j.state === "failed").length,
|
|
165
|
+
delayed: jobs.filter((j) => j.state === "delayed").length,
|
|
166
|
+
waiting: jobs.filter((j) => j.state === "waiting").length,
|
|
167
|
+
paused: jobs.filter((j) => j.state === "paused").length
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
async getScheduledJobs(queueName) {
|
|
171
|
+
const scheduled = [];
|
|
172
|
+
for (const [scheduleId, scheduledJob] of this.scheduledJobs.entries()) {
|
|
173
|
+
if (scheduledJob.queueName === queueName) {
|
|
174
|
+
const cronPattern = scheduledJob.opts.cron || scheduledJob.opts.repeat?.pattern;
|
|
175
|
+
let nextRun;
|
|
176
|
+
if (cronPattern) {
|
|
177
|
+
try {
|
|
178
|
+
const interval = cronParser.parseExpression(cronPattern);
|
|
179
|
+
nextRun = interval.next().toDate();
|
|
180
|
+
} catch {
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
scheduled.push({
|
|
184
|
+
id: scheduleId,
|
|
185
|
+
jobName: scheduledJob.job.name,
|
|
186
|
+
queueName: scheduledJob.queueName,
|
|
187
|
+
cron: scheduledJob.opts.cron,
|
|
188
|
+
pattern: scheduledJob.opts.repeat?.pattern,
|
|
189
|
+
nextRun,
|
|
190
|
+
repeatCount: scheduledJob.repeatCount,
|
|
191
|
+
limit: scheduledJob.opts.repeat?.limit
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return scheduled;
|
|
196
|
+
}
|
|
197
|
+
async removeScheduledJob(scheduleId) {
|
|
198
|
+
const scheduledJob = this.scheduledJobs.get(scheduleId);
|
|
199
|
+
if (!scheduledJob) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
if (scheduledJob.timerId) {
|
|
203
|
+
clearTimeout(scheduledJob.timerId);
|
|
204
|
+
}
|
|
205
|
+
this.scheduledJobs.delete(scheduleId);
|
|
206
|
+
console.info(`[FileQueue] Removed scheduled job: ${scheduleId}`);
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
async pause(queueName) {
|
|
210
|
+
const workerInfo = this.workers.get(queueName);
|
|
211
|
+
if (workerInfo) {
|
|
212
|
+
workerInfo.paused = true;
|
|
213
|
+
workerInfo.queue.pause();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
async resume(queueName) {
|
|
217
|
+
const workerInfo = this.workers.get(queueName);
|
|
218
|
+
if (workerInfo) {
|
|
219
|
+
workerInfo.paused = false;
|
|
220
|
+
workerInfo.queue.resume();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
async close() {
|
|
224
|
+
for (const [scheduleId, scheduledJob] of this.scheduledJobs.entries()) {
|
|
225
|
+
if (scheduledJob.timerId) {
|
|
226
|
+
clearTimeout(scheduledJob.timerId);
|
|
227
|
+
}
|
|
228
|
+
console.info(`[FileQueue] Stopped scheduled job: ${scheduleId}`);
|
|
229
|
+
}
|
|
230
|
+
this.scheduledJobs.clear();
|
|
231
|
+
const drainPromises = Array.from(this.workers.values()).map((w) => w.queue.drained());
|
|
232
|
+
await Promise.all(drainPromises);
|
|
233
|
+
const persistPromises = [];
|
|
234
|
+
for (const [_jobId, job] of Array.from(this.jobs.entries())) {
|
|
235
|
+
const queueName = job.data?.__queueName || "default";
|
|
236
|
+
persistPromises.push(this.persistJob(queueName, job));
|
|
237
|
+
}
|
|
238
|
+
await Promise.all(persistPromises);
|
|
239
|
+
this.jobs.clear();
|
|
240
|
+
this.eventListeners.clear();
|
|
241
|
+
this.workers.clear();
|
|
242
|
+
}
|
|
243
|
+
// ============================================================
|
|
244
|
+
// Worker Management
|
|
245
|
+
// ============================================================
|
|
246
|
+
registerWorker(queueName, jobName, handler, opts) {
|
|
247
|
+
const requestedConcurrency = opts?.concurrency || 1;
|
|
248
|
+
let workerInfo = this.workers.get(queueName);
|
|
249
|
+
if (workerInfo) {
|
|
250
|
+
console.info(`[FileQueue] Adding handler for job "${jobName}" to queue "${queueName}"`);
|
|
251
|
+
workerInfo.handlers.set(jobName, handler);
|
|
252
|
+
if (requestedConcurrency > workerInfo.concurrency) {
|
|
253
|
+
workerInfo.concurrency = requestedConcurrency;
|
|
254
|
+
workerInfo.queue.concurrency = requestedConcurrency;
|
|
255
|
+
console.info(`[FileQueue] Updated queue "${queueName}" concurrency to ${requestedConcurrency}`);
|
|
256
|
+
}
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
console.info(`[FileQueue] Creating new worker for queue: ${queueName}`);
|
|
260
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
261
|
+
handlers.set(jobName, handler);
|
|
262
|
+
const dispatcher = async (task) => {
|
|
263
|
+
const handler2 = handlers.get(task.jobName);
|
|
264
|
+
if (!handler2) {
|
|
265
|
+
const error = `No handler for job "${task.jobName}" on queue "${queueName}". Available: ${Array.from(handlers.keys()).join(", ")}`;
|
|
266
|
+
console.error(error);
|
|
267
|
+
throw new Error(error);
|
|
268
|
+
}
|
|
269
|
+
const storedJob = this.jobs.get(task.jobId);
|
|
270
|
+
if (!storedJob) {
|
|
271
|
+
throw new Error(`Job ${task.jobId} not found`);
|
|
272
|
+
}
|
|
273
|
+
const currentAttempts = storedJob.attemptsMade || 0;
|
|
274
|
+
const maxAttempts = storedJob.opts?.attempts || 1;
|
|
275
|
+
await this.updateJobState(queueName, task.jobId, "active", {
|
|
276
|
+
processedOn: Date.now()
|
|
277
|
+
});
|
|
278
|
+
this.emitEvent(queueName, "active", { jobId: task.jobId });
|
|
279
|
+
try {
|
|
280
|
+
const jobLike = {
|
|
281
|
+
id: task.jobId,
|
|
282
|
+
name: task.jobName,
|
|
283
|
+
data: task.data,
|
|
284
|
+
attemptsMade: currentAttempts,
|
|
285
|
+
opts: { attempts: maxAttempts, ...storedJob.opts }
|
|
286
|
+
};
|
|
287
|
+
const result = await handler2(jobLike, {});
|
|
288
|
+
if (result && typeof result === "object" && result.awaiting === true) {
|
|
289
|
+
this.jobs.delete(task.jobId);
|
|
290
|
+
await this.deleteJobFile(queueName, task.jobId);
|
|
291
|
+
return result;
|
|
292
|
+
}
|
|
293
|
+
await this.updateJobState(queueName, task.jobId, "completed", {
|
|
294
|
+
returnvalue: result,
|
|
295
|
+
finishedOn: Date.now()
|
|
296
|
+
});
|
|
297
|
+
this.emitEvent(queueName, "completed", { jobId: task.jobId, returnvalue: result });
|
|
298
|
+
await this.cleanupCompletedJobs(queueName, storedJob.opts?.removeOnComplete);
|
|
299
|
+
return result;
|
|
300
|
+
} catch (err) {
|
|
301
|
+
const newAttemptCount = currentAttempts + 1;
|
|
302
|
+
if (newAttemptCount < maxAttempts) {
|
|
303
|
+
let retryDelay = 0;
|
|
304
|
+
if (storedJob.opts?.backoff) {
|
|
305
|
+
const { type, delay } = storedJob.opts.backoff;
|
|
306
|
+
if (type === "exponential") {
|
|
307
|
+
retryDelay = delay * Math.pow(2, newAttemptCount - 1);
|
|
308
|
+
} else {
|
|
309
|
+
retryDelay = delay;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
await this.updateJobState(queueName, task.jobId, "waiting", {
|
|
313
|
+
attemptsMade: newAttemptCount,
|
|
314
|
+
failedReason: `Attempt ${newAttemptCount}/${maxAttempts} failed: ${err.message}`
|
|
315
|
+
});
|
|
316
|
+
console.info(
|
|
317
|
+
`[FileQueue] Retrying job ${task.jobId} (attempt ${newAttemptCount + 1}/${maxAttempts}) after ${retryDelay}ms delay`
|
|
318
|
+
);
|
|
319
|
+
const currentWorkerInfo = this.workers.get(queueName);
|
|
320
|
+
if (currentWorkerInfo) {
|
|
321
|
+
setTimeout(() => {
|
|
322
|
+
currentWorkerInfo.queue.push(task).catch(() => {
|
|
323
|
+
});
|
|
324
|
+
}, retryDelay);
|
|
325
|
+
}
|
|
326
|
+
throw err;
|
|
327
|
+
}
|
|
328
|
+
await this.updateJobState(queueName, task.jobId, "failed", {
|
|
329
|
+
failedReason: `Failed after ${newAttemptCount} attempts: ${err.message}`,
|
|
330
|
+
finishedOn: Date.now(),
|
|
331
|
+
attemptsMade: newAttemptCount
|
|
332
|
+
});
|
|
333
|
+
this.emitEvent(queueName, "failed", {
|
|
334
|
+
jobId: task.jobId,
|
|
335
|
+
failedReason: err.message,
|
|
336
|
+
attemptsMade: newAttemptCount,
|
|
337
|
+
maxAttempts
|
|
338
|
+
});
|
|
339
|
+
await this.cleanupFailedJobs(queueName, storedJob.opts?.removeOnFail);
|
|
340
|
+
throw err;
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
const concurrency = opts?.concurrency || 1;
|
|
344
|
+
const queue = fastq.promise(dispatcher, concurrency);
|
|
345
|
+
const shouldPause = opts?.autorun === false;
|
|
346
|
+
workerInfo = {
|
|
347
|
+
queue,
|
|
348
|
+
handlers,
|
|
349
|
+
paused: shouldPause || false,
|
|
350
|
+
concurrency
|
|
351
|
+
};
|
|
352
|
+
if (shouldPause) {
|
|
353
|
+
queue.pause();
|
|
354
|
+
console.info(`[FileQueue] Worker for "${queueName}" created but paused`);
|
|
355
|
+
}
|
|
356
|
+
this.workers.set(queueName, workerInfo);
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Start processing waiting jobs for a queue
|
|
360
|
+
* Should be called after all handlers are registered
|
|
361
|
+
*/
|
|
362
|
+
startProcessingQueue(queueName) {
|
|
363
|
+
const workerInfo = this.workers.get(queueName);
|
|
364
|
+
if (!workerInfo || workerInfo.paused) return;
|
|
365
|
+
const waitingJobs = Array.from(this.jobs.values()).filter(
|
|
366
|
+
(j) => j.state === "waiting" && j.data?.__queueName === queueName
|
|
367
|
+
);
|
|
368
|
+
for (const job of waitingJobs) {
|
|
369
|
+
workerInfo.queue.push({ jobId: job.id, jobName: job.name, data: job.data }).catch(() => {
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
// ============================================================
|
|
374
|
+
// Helper Methods
|
|
375
|
+
// ============================================================
|
|
376
|
+
async updateJobState(queueName, jobId, state, extra) {
|
|
377
|
+
const job = this.jobs.get(jobId);
|
|
378
|
+
if (job) {
|
|
379
|
+
job.state = state;
|
|
380
|
+
if (extra) {
|
|
381
|
+
Object.assign(job, extra);
|
|
382
|
+
}
|
|
383
|
+
await this.persistJob(queueName, job);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
emitEvent(queueName, event, payload) {
|
|
387
|
+
const key = `${queueName}:${event}`;
|
|
388
|
+
const listeners = this.eventListeners.get(key) || [];
|
|
389
|
+
for (const callback of listeners) {
|
|
390
|
+
try {
|
|
391
|
+
callback(payload);
|
|
392
|
+
} catch (error) {
|
|
393
|
+
console.error(`[FileQueueAdapter] Error in event listener for ${key}:`, error);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Clean up completed jobs based on removeOnComplete option
|
|
399
|
+
* - true: delete immediately
|
|
400
|
+
* - false/undefined: keep forever
|
|
401
|
+
* - number: keep last N jobs, delete older ones
|
|
402
|
+
*/
|
|
403
|
+
async cleanupCompletedJobs(queueName, removeOnComplete) {
|
|
404
|
+
if (removeOnComplete === false || removeOnComplete === void 0) {
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
if (removeOnComplete === true) {
|
|
408
|
+
const completedJobs = Array.from(this.jobs.values()).filter(
|
|
409
|
+
(j) => j.state === "completed" && j.data?.__queueName === queueName
|
|
410
|
+
);
|
|
411
|
+
for (const job of completedJobs) {
|
|
412
|
+
this.jobs.delete(job.id);
|
|
413
|
+
await this.deleteJobFile(queueName, job.id);
|
|
414
|
+
}
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
if (typeof removeOnComplete === "number") {
|
|
418
|
+
const completedJobs = Array.from(this.jobs.values()).filter((j) => j.state === "completed" && j.data?.__queueName === queueName).sort((a, b) => (b.finishedOn || 0) - (a.finishedOn || 0));
|
|
419
|
+
const jobsToDelete = completedJobs.slice(removeOnComplete);
|
|
420
|
+
for (const job of jobsToDelete) {
|
|
421
|
+
this.jobs.delete(job.id);
|
|
422
|
+
await this.deleteJobFile(queueName, job.id);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Clean up failed jobs based on removeOnFail option
|
|
428
|
+
* - true: delete immediately
|
|
429
|
+
* - false/undefined: keep forever
|
|
430
|
+
* - number: keep last N jobs, delete older ones
|
|
431
|
+
*/
|
|
432
|
+
async cleanupFailedJobs(queueName, removeOnFail) {
|
|
433
|
+
if (removeOnFail === false || removeOnFail === void 0) {
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
if (removeOnFail === true) {
|
|
437
|
+
const failedJobs = Array.from(this.jobs.values()).filter(
|
|
438
|
+
(j) => j.state === "failed" && j.data?.__queueName === queueName
|
|
439
|
+
);
|
|
440
|
+
for (const job of failedJobs) {
|
|
441
|
+
this.jobs.delete(job.id);
|
|
442
|
+
await this.deleteJobFile(queueName, job.id);
|
|
443
|
+
}
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
if (typeof removeOnFail === "number") {
|
|
447
|
+
const failedJobs = Array.from(this.jobs.values()).filter((j) => j.state === "failed" && j.data?.__queueName === queueName).sort((a, b) => (b.finishedOn || 0) - (a.finishedOn || 0));
|
|
448
|
+
const jobsToDelete = failedJobs.slice(removeOnFail);
|
|
449
|
+
for (const job of jobsToDelete) {
|
|
450
|
+
this.jobs.delete(job.id);
|
|
451
|
+
await this.deleteJobFile(queueName, job.id);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
generateId() {
|
|
456
|
+
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
457
|
+
}
|
|
458
|
+
scheduleCronJob(scheduleId, scheduledJob) {
|
|
459
|
+
const cronPattern = scheduledJob.opts.cron || scheduledJob.opts.repeat?.pattern;
|
|
460
|
+
if (!cronPattern) {
|
|
461
|
+
console.error(`[FileQueue] No cron pattern found for schedule ${scheduleId}`);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
try {
|
|
465
|
+
const interval = cronParser.parseExpression(cronPattern);
|
|
466
|
+
const nextRun = interval.next().toDate();
|
|
467
|
+
const now = /* @__PURE__ */ new Date();
|
|
468
|
+
const delay = nextRun.getTime() - now.getTime();
|
|
469
|
+
console.info(
|
|
470
|
+
`[FileQueue] Next run for schedule ${scheduleId}: ${nextRun.toISOString()} (in ${Math.round(delay / 1e3)}s)`
|
|
471
|
+
);
|
|
472
|
+
scheduledJob.timerId = setTimeout(async () => {
|
|
473
|
+
const limit = scheduledJob.opts.repeat?.limit;
|
|
474
|
+
if (limit !== void 0 && scheduledJob.repeatCount >= limit) {
|
|
475
|
+
console.info(`[FileQueue] Schedule ${scheduleId} reached repeat limit (${limit})`);
|
|
476
|
+
this.scheduledJobs.delete(scheduleId);
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
try {
|
|
480
|
+
await this.enqueue(scheduledJob.queueName, scheduledJob.job);
|
|
481
|
+
scheduledJob.repeatCount++;
|
|
482
|
+
const shouldContinue = limit === void 0 || scheduledJob.repeatCount < limit;
|
|
483
|
+
if (shouldContinue) {
|
|
484
|
+
this.scheduleCronJob(scheduleId, scheduledJob);
|
|
485
|
+
} else {
|
|
486
|
+
console.info(`[FileQueue] Schedule ${scheduleId} completed all ${limit} runs`);
|
|
487
|
+
this.scheduledJobs.delete(scheduleId);
|
|
488
|
+
}
|
|
489
|
+
} catch (error) {
|
|
490
|
+
console.error(`[FileQueue] Error executing scheduled job ${scheduleId}:`, error);
|
|
491
|
+
this.scheduleCronJob(scheduleId, scheduledJob);
|
|
492
|
+
}
|
|
493
|
+
}, delay);
|
|
494
|
+
} catch (error) {
|
|
495
|
+
console.error(`[FileQueue] Error parsing cron expression "${cronPattern}":`, error);
|
|
496
|
+
throw new Error(`Invalid cron pattern: ${cronPattern}`);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Store Adapter
|
|
3
|
+
*
|
|
4
|
+
* File-based storage for development/small deployments
|
|
5
|
+
* - Extends MemoryStoreAdapter with persistence
|
|
6
|
+
* - Fast in-memory access backed by file system
|
|
7
|
+
* - Survives restarts
|
|
8
|
+
* - Single instance only
|
|
9
|
+
*
|
|
10
|
+
* Storage format:
|
|
11
|
+
* - {dataDir}/streams/{subject}.ndjson - Event streams (append-only NDJSON)
|
|
12
|
+
* - {dataDir}/indices/{key}.json - Sorted indices (JSON arrays)
|
|
13
|
+
* - {dataDir}/kv/{key}.json - KV store (individual JSON files)
|
|
14
|
+
*/
|
|
15
|
+
import { MemoryStoreAdapter } from './memory-store.js';
|
|
16
|
+
export interface FileStoreAdapterOptions {
|
|
17
|
+
dataDir: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* File-backed store adapter
|
|
21
|
+
* Extends memory store and persists on every write using same format as existing file adapter
|
|
22
|
+
*/
|
|
23
|
+
export declare class FileStoreAdapter extends MemoryStoreAdapter {
|
|
24
|
+
private options;
|
|
25
|
+
constructor(options: FileStoreAdapterOptions);
|
|
26
|
+
private streamPath;
|
|
27
|
+
private indexPath;
|
|
28
|
+
private kvPath;
|
|
29
|
+
init(): Promise<void>;
|
|
30
|
+
private loadFromDisk;
|
|
31
|
+
close(): Promise<void>;
|
|
32
|
+
}
|