@unchainedshop/core-worker 4.0.0-rc.9 → 4.0.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.
Files changed (52) hide show
  1. package/lib/db/WorkQueueCollection.d.ts +2 -2
  2. package/lib/db/WorkQueueCollection.d.ts.map +1 -1
  3. package/lib/db/WorkQueueCollection.js +17 -13
  4. package/lib/db/WorkQueueCollection.js.map +1 -1
  5. package/lib/db/WorkQueueSchema.d.ts +3 -0
  6. package/lib/db/WorkQueueSchema.d.ts.map +1 -0
  7. package/lib/db/WorkQueueSchema.js +20 -0
  8. package/lib/db/WorkQueueSchema.js.map +1 -0
  9. package/lib/director/WorkStatus.d.ts +8 -0
  10. package/lib/director/WorkStatus.d.ts.map +1 -0
  11. package/lib/director/WorkStatus.js +9 -0
  12. package/lib/director/WorkStatus.js.map +1 -0
  13. package/lib/director/WorkerAdapter.d.ts +3 -0
  14. package/lib/director/WorkerAdapter.d.ts.map +1 -0
  15. package/lib/director/WorkerAdapter.js +11 -0
  16. package/lib/director/WorkerAdapter.js.map +1 -0
  17. package/lib/director/WorkerDirector.d.ts +4 -0
  18. package/lib/director/WorkerDirector.d.ts.map +1 -0
  19. package/lib/director/WorkerDirector.js +72 -0
  20. package/lib/director/WorkerDirector.js.map +1 -0
  21. package/lib/director/WorkerEventTypes.d.ts +8 -0
  22. package/lib/director/WorkerEventTypes.d.ts.map +1 -0
  23. package/lib/director/WorkerEventTypes.js +12 -0
  24. package/lib/director/WorkerEventTypes.js.map +1 -0
  25. package/lib/module/configureWorkerModule.d.ts +34 -35
  26. package/lib/module/configureWorkerModule.d.ts.map +1 -1
  27. package/lib/module/configureWorkerModule.js +21 -10
  28. package/lib/module/configureWorkerModule.js.map +1 -1
  29. package/lib/module/migrations/addMigrations.d.ts +3 -0
  30. package/lib/module/migrations/addMigrations.d.ts.map +1 -0
  31. package/lib/module/migrations/addMigrations.js +16 -0
  32. package/lib/module/migrations/addMigrations.js.map +1 -0
  33. package/lib/schedulers/FailedRescheduler.d.ts +6 -0
  34. package/lib/schedulers/FailedRescheduler.d.ts.map +1 -0
  35. package/lib/schedulers/FailedRescheduler.js +45 -0
  36. package/lib/schedulers/FailedRescheduler.js.map +1 -0
  37. package/lib/workers/BaseWorker.d.ts +8 -0
  38. package/lib/workers/BaseWorker.d.ts.map +1 -0
  39. package/lib/workers/BaseWorker.js +81 -0
  40. package/lib/workers/BaseWorker.js.map +1 -0
  41. package/lib/workers/EventListenerWorker.d.ts +6 -0
  42. package/lib/workers/EventListenerWorker.d.ts.map +1 -0
  43. package/lib/workers/EventListenerWorker.js +46 -0
  44. package/lib/workers/EventListenerWorker.js.map +1 -0
  45. package/lib/workers/IntervalWorker.d.ts +9 -0
  46. package/lib/workers/IntervalWorker.d.ts.map +1 -0
  47. package/lib/workers/IntervalWorker.js +38 -0
  48. package/lib/workers/IntervalWorker.js.map +1 -0
  49. package/package.json +3 -3
  50. package/src/db/WorkQueueCollection.ts +20 -15
  51. package/src/module/configureWorkerModule.ts +57 -46
  52. package/tsconfig.json +2 -1
@@ -0,0 +1,16 @@
1
+ import { WorkQueueCollection } from '../../db/WorkQueueCollection.js';
2
+ export default function addMigrations(repository) {
3
+ repository?.register({
4
+ id: 20240905161400,
5
+ name: 'Remove all autoscheduled work items so they get scheduled freshly',
6
+ up: async () => {
7
+ const WorkQueue = await WorkQueueCollection(repository.db);
8
+ await WorkQueue.deleteMany({
9
+ autoscheduled: true,
10
+ started: null,
11
+ deleted: null,
12
+ });
13
+ },
14
+ });
15
+ }
16
+ //# sourceMappingURL=addMigrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addMigrations.js","sourceRoot":"","sources":["../../../src/module/migrations/addMigrations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAEtE,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,UAA0C;IAC9E,UAAU,EAAE,QAAQ,CAAC;QACnB,EAAE,EAAE,cAAc;QAClB,IAAI,EAAE,mEAAmE;QACzE,EAAE,EAAE,KAAK,IAAI,EAAE;YACb,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;YAE3D,MAAM,SAAS,CAAC,UAAU,CAAC;gBACzB,aAAa,EAAE,IAAI;gBACnB,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { IScheduler, WorkData } from '@unchainedshop/types/worker.js';
2
+ export interface FailedReschedulerParams {
3
+ retryInput?: (workData: WorkData, priorInput: Record<string, any>) => Promise<Record<string, any> | null>;
4
+ }
5
+ export declare const FailedRescheduler: IScheduler<FailedReschedulerParams>;
6
+ //# sourceMappingURL=FailedRescheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FailedRescheduler.d.ts","sourceRoot":"","sources":["../../src/schedulers/FailedRescheduler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAQ,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAK5E,MAAM,WAAW,uBAAuB;IACtC,UAAU,CAAC,EAAE,CACX,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAC5B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;CAC1C;AAED,eAAO,MAAM,iBAAiB,EAAE,UAAU,CAAC,uBAAuB,CAsDjE,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { log } from '@unchainedshop/logger';
2
+ import { subscribe } from '@unchainedshop/events';
3
+ import { WorkerEventTypes } from '../director/WorkerEventTypes.js';
4
+ export const FailedRescheduler = {
5
+ key: 'shop.unchained.scheduler.failed',
6
+ label: 'Reschedule failed works',
7
+ version: '1.0.0',
8
+ actions: ({ retryInput }, unchainedAPI) => {
9
+ const handleFinishedWork = async ({ payload: work }) => {
10
+ if (!work.success && work.retries > 0) {
11
+ const now = new Date();
12
+ const workDelayMs = work.scheduled.getTime() - work.created.getTime();
13
+ // In short: Double the delay of the old work or delay for 5 seconds
14
+ const scheduled = workDelayMs > 1000
15
+ ? new Date(now.getTime() + workDelayMs * 2)
16
+ : new Date(now.setSeconds(now.getSeconds() + 5));
17
+ log(`${FailedRescheduler.key} -> Reschedule failed work ${work._id} ${work.type} for ${scheduled.toISOString()} (in ${Math.round(workDelayMs / 1000)}). Remaining retries: ${work.retries}`);
18
+ const workData = {
19
+ type: work.type,
20
+ priority: work.priority,
21
+ originalWorkId: work.originalWorkId || work._id,
22
+ retries: work.retries - 1,
23
+ timeout: work.timeout,
24
+ scheduled,
25
+ };
26
+ if (retryInput) {
27
+ workData.input = await retryInput(workData, work.input);
28
+ }
29
+ else {
30
+ workData.input = work.input;
31
+ }
32
+ unchainedAPI.modules.worker.addWork(workData);
33
+ }
34
+ };
35
+ return {
36
+ start() {
37
+ subscribe(WorkerEventTypes.FINISHED, handleFinishedWork);
38
+ },
39
+ stop() {
40
+ /* */
41
+ },
42
+ };
43
+ },
44
+ };
45
+ //# sourceMappingURL=FailedRescheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FailedRescheduler.js","sourceRoot":"","sources":["../../src/schedulers/FailedRescheduler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AASnE,MAAM,CAAC,MAAM,iBAAiB,GAAwC;IACpE,GAAG,EAAE,iCAAiC;IACtC,KAAK,EAAE,yBAAyB;IAChC,OAAO,EAAE,OAAO;IAEhB,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,YAAY,EAAE,EAAE;QACxC,MAAM,kBAAkB,GAAG,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAqB,EAAE,EAAE;YACxE,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;gBACtC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;gBAEtE,oEAAoE;gBACpE,MAAM,SAAS,GACb,WAAW,GAAG,IAAI;oBAChB,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,WAAW,GAAG,CAAC,CAAC;oBAC3C,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;gBAErD,GAAG,CACD,GAAG,iBAAiB,CAAC,GAAG,8BAA8B,IAAI,CAAC,GAAG,IAC5D,IAAI,CAAC,IACP,QAAQ,SAAS,CAAC,WAAW,EAAE,QAAQ,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,yBACnE,IAAI,CAAC,OACP,EAAE,CACH,CAAC;gBAEF,MAAM,QAAQ,GAAa;oBACzB,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,cAAc,EAAE,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,GAAG;oBAC/C,OAAO,EAAE,IAAI,CAAC,OAAO,GAAG,CAAC;oBACzB,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,SAAS;iBACV,CAAC;gBAEF,IAAI,UAAU,EAAE,CAAC;oBACf,QAAQ,CAAC,KAAK,GAAG,MAAM,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC1D,CAAC;qBAAM,CAAC;oBACN,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;gBAC9B,CAAC;gBAED,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAChD,CAAC;QACH,CAAC,CAAC;QAEF,OAAO;YACL,KAAK;gBACH,SAAS,CAAO,gBAAgB,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;YACjE,CAAC;YAED,IAAI;gBACF,KAAK;YACP,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { IWorker } from '@unchainedshop/types/worker.js';
2
+ interface WorkerParams {
3
+ workerId?: string;
4
+ worker: IWorker<any>;
5
+ }
6
+ export declare const BaseWorker: IWorker<WorkerParams>;
7
+ export {};
8
+ //# sourceMappingURL=BaseWorker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseWorker.d.ts","sourceRoot":"","sources":["../../src/workers/BaseWorker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAY,MAAM,gCAAgC,CAAC;AAKnE,UAAU,YAAY;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;CACtB;AAED,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,YAAY,CAuF5C,CAAC"}
@@ -0,0 +1,81 @@
1
+ import later from '@breejs/later';
2
+ import { log } from '@unchainedshop/logger';
3
+ import { WorkerDirector } from '../director/WorkerDirector.js';
4
+ export const BaseWorker = {
5
+ key: 'shop.unchained.worker.base',
6
+ label: 'Base worker. Do not use this directly.',
7
+ version: '1.0.0',
8
+ type: 'BASE',
9
+ external: false,
10
+ getFloorDate: (date = new Date()) => {
11
+ const floored = new Date(Math.floor(date.getTime() / 1000) * 1000);
12
+ return floored;
13
+ },
14
+ actions: ({ workerId, worker }, unchainedAPI) => {
15
+ log(`${worker.key} -> Initialized ${worker.type}`);
16
+ const workerActions = {
17
+ start() {
18
+ throw new Error(`Not implemented on ${this.constructor.key}`);
19
+ },
20
+ stop() {
21
+ throw new Error(`Not implemented on ${this.constructor.key}`);
22
+ },
23
+ reset: async (referenceDate = new Date()) => {
24
+ await unchainedAPI.modules.worker.markOldWorkAsFailed({
25
+ types: WorkerDirector.getActivePluginTypes({ external: false }),
26
+ worker: workerId,
27
+ referenceDate,
28
+ });
29
+ },
30
+ autorescheduleTypes: async ({ referenceDate }) => {
31
+ return Promise.all(WorkerDirector.getAutoSchedules().map(async ([scheduleId, workConfig]) => {
32
+ if (!workConfig.schedule) {
33
+ await unchainedAPI.modules.worker.ensureNoWork({
34
+ type: workConfig.type,
35
+ priority: workConfig.priority || 0,
36
+ scheduleId,
37
+ });
38
+ return null;
39
+ }
40
+ const fixedSchedule = { ...workConfig.schedule };
41
+ fixedSchedule.schedules[0].s = [0]; // ignore seconds, always run on second 0
42
+ const nextDate = later.schedule(fixedSchedule).next(1, referenceDate);
43
+ nextDate.setMilliseconds(0);
44
+ const workData = {
45
+ type: workConfig.type,
46
+ scheduleId,
47
+ scheduled: nextDate,
48
+ timeout: workConfig.timeout,
49
+ priority: workConfig.priority || 0,
50
+ retries: workConfig.retries || 0,
51
+ };
52
+ if (workConfig.input) {
53
+ workData.input = await workConfig.input(workData);
54
+ // A work input fn can skip auto scheduling a new record
55
+ // when it explicitly returns a falsish input instead of a dictionary
56
+ if (!workData.input)
57
+ return null;
58
+ }
59
+ return unchainedAPI.modules.worker.ensureOneWork(workData);
60
+ }));
61
+ },
62
+ process: async ({ maxWorkItemCount, referenceDate }) => {
63
+ await workerActions.autorescheduleTypes({
64
+ referenceDate,
65
+ });
66
+ const processRecursively = async (recursionCounter = 0) => {
67
+ if (maxWorkItemCount && maxWorkItemCount < recursionCounter)
68
+ return null;
69
+ const doneWork = await unchainedAPI.modules.worker.processNextWork(unchainedAPI, workerId);
70
+ if (doneWork)
71
+ return processRecursively(recursionCounter + 1);
72
+ return null;
73
+ };
74
+ await processRecursively();
75
+ },
76
+ };
77
+ workerActions.reset();
78
+ return workerActions;
79
+ },
80
+ };
81
+ //# sourceMappingURL=BaseWorker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseWorker.js","sourceRoot":"","sources":["../../src/workers/BaseWorker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { IWorker } from '@unchainedshop/types/worker.js';
2
+ export interface EventListenerWorkerParams {
3
+ workerId?: string;
4
+ }
5
+ export declare const EventListenerWorker: IWorker<EventListenerWorkerParams>;
6
+ //# sourceMappingURL=EventListenerWorker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventListenerWorker.d.ts","sourceRoot":"","sources":["../../src/workers/EventListenerWorker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAgBzD,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,mBAAmB,EAAE,OAAO,CAAC,yBAAyB,CAyClE,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { subscribe } from '@unchainedshop/events';
2
+ import { WorkerEventTypes } from '../director/WorkerEventTypes.js';
3
+ import { BaseWorker } from './BaseWorker.js';
4
+ function debounce(func, wait) {
5
+ let timeout;
6
+ return (...args) => {
7
+ clearTimeout(timeout);
8
+ timeout = setTimeout(() => {
9
+ timeout = null;
10
+ func(...args);
11
+ }, wait);
12
+ };
13
+ }
14
+ export const EventListenerWorker = {
15
+ ...BaseWorker,
16
+ key: 'shop.unchained.worker.event-listener',
17
+ label: 'Allocates work on events. This worker does not make sense on multiple containers.',
18
+ version: '1.0.0',
19
+ type: 'EVENT_LISTENER',
20
+ actions: ({ workerId }, unchainedAPI) => {
21
+ const baseWorkerActions = BaseWorker.actions({ workerId, worker: EventListenerWorker }, unchainedAPI);
22
+ // Debounce in the event of many work queue events conflicting with each other
23
+ const processWorkQueue = debounce(async () => {
24
+ await baseWorkerActions.process({
25
+ maxWorkItemCount: 1, // only one work item at a time, else we could end up in a loop
26
+ referenceDate: EventListenerWorker.getFloorDate(),
27
+ });
28
+ }, 300);
29
+ return {
30
+ ...baseWorkerActions,
31
+ start() {
32
+ subscribe(WorkerEventTypes.ADDED, processWorkQueue);
33
+ subscribe(WorkerEventTypes.FINISHED, processWorkQueue);
34
+ setTimeout(async () => {
35
+ await baseWorkerActions.autorescheduleTypes({
36
+ referenceDate: EventListenerWorker.getFloorDate(),
37
+ });
38
+ }, 300);
39
+ },
40
+ stop() {
41
+ /* */
42
+ },
43
+ };
44
+ },
45
+ };
46
+ //# sourceMappingURL=EventListenerWorker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventListenerWorker.js","sourceRoot":"","sources":["../../src/workers/EventListenerWorker.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,SAAS,QAAQ,CAAkC,IAAO,EAAE,IAAI;IAC9D,IAAI,OAAO,CAAC;IACZ,OAAO,CAAC,GAAG,IAAI,EAAE,EAAE;QACjB,YAAY,CAAC,OAAO,CAAC,CAAC;QACtB,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YACxB,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QAChB,CAAC,EAAE,IAAI,CAAC,CAAC;IACX,CAAC,CAAC;AACJ,CAAC;AAMD,MAAM,CAAC,MAAM,mBAAmB,GAAuC;IACrE,GAAG,UAAU;IAEb,GAAG,EAAE,sCAAsC;IAC3C,KAAK,EAAE,mFAAmF;IAC1F,OAAO,EAAE,OAAO;IAChB,IAAI,EAAE,gBAAgB;IAEtB,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,EAAE;QACtC,MAAM,iBAAiB,GAAG,UAAU,CAAC,OAAO,CAC1C,EAAE,QAAQ,EAAE,MAAM,EAAE,mBAAmB,EAAE,EACzC,YAAY,CACb,CAAC;QAEF,8EAA8E;QAC9E,MAAM,gBAAgB,GAAG,QAAQ,CAAsB,KAAK,IAAI,EAAE;YAChE,MAAM,iBAAiB,CAAC,OAAO,CAAC;gBAC9B,gBAAgB,EAAE,CAAC,EAAE,+DAA+D;gBACpF,aAAa,EAAE,mBAAmB,CAAC,YAAY,EAAE;aAClD,CAAC,CAAC;QACL,CAAC,EAAE,GAAG,CAAC,CAAC;QAER,OAAO;YACL,GAAG,iBAAiB;YAEpB,KAAK;gBACH,SAAS,CAAC,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;gBACpD,SAAS,CAAC,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;gBAEvD,UAAU,CAAC,KAAK,IAAI,EAAE;oBACpB,MAAM,iBAAiB,CAAC,mBAAmB,CAAC;wBAC1C,aAAa,EAAE,mBAAmB,CAAC,YAAY,EAAE;qBAClD,CAAC,CAAC;gBACL,CAAC,EAAE,GAAG,CAAC,CAAC;YACV,CAAC;YAED,IAAI;gBACF,KAAK;YACP,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { IWorker, WorkerSchedule } from '@unchainedshop/types/worker.js';
2
+ export interface IntervalWorkerParams {
3
+ workerId?: string;
4
+ batchCount?: number;
5
+ schedule?: WorkerSchedule | string;
6
+ }
7
+ export declare const scheduleToInterval: (scheduleRaw: WorkerSchedule | string) => number;
8
+ export declare const IntervalWorker: IWorker<IntervalWorkerParams>;
9
+ //# sourceMappingURL=IntervalWorker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntervalWorker.d.ts","sourceRoot":"","sources":["../../src/workers/IntervalWorker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAMzE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC;CACpC;AAMD,eAAO,MAAM,kBAAkB,gBAAiB,cAAc,GAAG,MAAM,WAMtE,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,oBAAoB,CA+BxD,CAAC"}
@@ -0,0 +1,38 @@
1
+ import later from '@breejs/later';
2
+ import { BaseWorker } from './BaseWorker.js';
3
+ const { NODE_ENV } = process.env;
4
+ const defaultSchedule = later.parse.text(NODE_ENV !== 'production' ? 'every 2 seconds' : 'every 30 seconds');
5
+ export const scheduleToInterval = (scheduleRaw) => {
6
+ const referenceDate = new Date(1000);
7
+ const schedule = typeof scheduleRaw === 'string' ? later.parse.text(scheduleRaw) : scheduleRaw;
8
+ const [one, two] = later.schedule(schedule).next(2, referenceDate);
9
+ const diff = new Date(two).getTime() - new Date(one).getTime();
10
+ return Math.min(1000 * 60 * 60, diff); // at least once every hour!
11
+ };
12
+ export const IntervalWorker = {
13
+ ...BaseWorker,
14
+ key: 'shop.unchained.worker.cron',
15
+ label: 'Allocates work on fixed intervals with native node setInterval',
16
+ version: '1.0.0',
17
+ type: 'CRON',
18
+ actions: ({ workerId, batchCount = 0, schedule = defaultSchedule }, unchainedAPI) => {
19
+ const baseWorkerActions = BaseWorker.actions({ workerId, worker: IntervalWorker }, unchainedAPI);
20
+ const intervalDelay = scheduleToInterval(schedule);
21
+ let intervalHandle;
22
+ return {
23
+ ...baseWorkerActions,
24
+ start() {
25
+ intervalHandle = setInterval(() => {
26
+ baseWorkerActions.process({
27
+ maxWorkItemCount: batchCount,
28
+ referenceDate: IntervalWorker.getFloorDate(),
29
+ });
30
+ }, intervalDelay);
31
+ },
32
+ stop() {
33
+ clearInterval(intervalHandle);
34
+ },
35
+ };
36
+ },
37
+ };
38
+ //# sourceMappingURL=IntervalWorker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntervalWorker.js","sourceRoot":"","sources":["../../src/workers/IntervalWorker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,eAAe,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;AAQjC,MAAM,eAAe,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CACtC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,kBAAkB,CACjD,CAAC;AAEpB,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,WAAoC,EAAE,EAAE;IACzE,MAAM,aAAa,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;IAC/F,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAC/D,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,4BAA4B;AACrE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAkC;IAC3D,GAAG,UAAU;IAEb,GAAG,EAAE,4BAA4B;IACjC,KAAK,EAAE,gEAAgE;IACvE,OAAO,EAAE,OAAO;IAChB,IAAI,EAAE,MAAM;IAEZ,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,UAAU,GAAG,CAAC,EAAE,QAAQ,GAAG,eAAe,EAAE,EAAE,YAAY,EAAE,EAAE;QAClF,MAAM,iBAAiB,GAAG,UAAU,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,EAAE,YAAY,CAAC,CAAC;QAEjG,MAAM,aAAa,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,cAA8B,CAAC;QAEnC,OAAO;YACL,GAAG,iBAAiB;YAEpB,KAAK;gBACH,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE;oBAChC,iBAAiB,CAAC,OAAO,CAAC;wBACxB,gBAAgB,EAAE,UAAU;wBAC5B,aAAa,EAAE,cAAc,CAAC,YAAY,EAAE;qBAC7C,CAAC,CAAC;gBACL,CAAC,EAAE,aAAa,CAAC,CAAC;YACpB,CAAC;YAED,IAAI;gBACF,aAAa,CAAC,cAAc,CAAC,CAAC;YAChC,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unchainedshop/core-worker",
3
- "version": "4.0.0-rc.9",
3
+ "version": "4.0.0",
4
4
  "main": "lib/worker-index.js",
5
5
  "types": "lib/worker-index.d.ts",
6
6
  "type": "module",
@@ -31,8 +31,8 @@
31
31
  },
32
32
  "homepage": "https://github.com/unchainedshop/unchained#readme",
33
33
  "dependencies": {
34
- "@unchainedshop/logger": "^4.0.0-rc.4",
35
- "@unchainedshop/utils": "^4.0.0-rc.4"
34
+ "@unchainedshop/logger": "^4.0.0",
35
+ "@unchainedshop/utils": "^4.0.0"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/node": "^24.0.13",
@@ -12,7 +12,7 @@ export enum WorkStatus {
12
12
  }
13
13
 
14
14
  export type Work = {
15
- _id?: string;
15
+ _id: string;
16
16
  priority: number;
17
17
  retries: number;
18
18
  scheduled: Date;
@@ -25,7 +25,7 @@ export type Work = {
25
25
  started?: Date;
26
26
  success?: boolean;
27
27
  timeout?: number;
28
- worker?: string;
28
+ worker?: string | null;
29
29
  autoscheduled?: boolean;
30
30
  scheduleId?: string;
31
31
  } & TimestampFields;
@@ -33,6 +33,24 @@ export type Work = {
33
33
  export const WorkQueueCollection = async (db: mongodb.Db) => {
34
34
  const WorkQueue = db.collection<Work>('work_queue');
35
35
 
36
+ if (!isDocumentDBCompatModeEnabled()) {
37
+ await buildDbIndexes<Work>(WorkQueue, [
38
+ {
39
+ index: { originalWorkId: 'text', _id: 'text', worker: 'text', input: 'text', type: 'text' },
40
+ options: {
41
+ weights: {
42
+ _id: 8,
43
+ originalWorkId: 6,
44
+ type: 5,
45
+ worker: 4,
46
+ input: 2,
47
+ },
48
+ name: 'workqueue_fulltext_search',
49
+ },
50
+ },
51
+ ]);
52
+ }
53
+
36
54
  await buildDbIndexes<Work>(WorkQueue, [
37
55
  {
38
56
  index: { created: -1 },
@@ -44,19 +62,6 @@ export const WorkQueueCollection = async (db: mongodb.Db) => {
44
62
  { index: { priority: -1 } },
45
63
  { index: { type: 1 } },
46
64
  { index: { originalWorkId: 1 } },
47
- !isDocumentDBCompatModeEnabled() && {
48
- index: { originalWorkId: 'text', _id: 'text', worker: 'text', input: 'text', type: 'text' },
49
- options: {
50
- weights: {
51
- _id: 8,
52
- originalWorkId: 6,
53
- type: 5,
54
- worker: 4,
55
- input: 2,
56
- },
57
- name: 'workqueue_fulltext_search',
58
- },
59
- },
60
65
  ]);
61
66
 
62
67
  return WorkQueue;
@@ -25,8 +25,9 @@ const logger = createLogger('unchained:core-worker');
25
25
 
26
26
  export type WorkData = Pick<
27
27
  Partial<Work>,
28
- 'input' | 'originalWorkId' | 'priority' | 'retries' | 'timeout' | 'scheduled' | 'worker' | 'scheduleId'
29
- > & { type: string };
28
+ 'input' | 'originalWorkId' | 'priority' | 'retries' | 'timeout' | 'worker' | 'scheduleId'
29
+ > &
30
+ Pick<Work, 'type' | 'scheduled'>;
30
31
 
31
32
  export interface WorkResult<Result = unknown> {
32
33
  success: boolean;
@@ -58,7 +59,7 @@ export interface WorkerReport {
58
59
  export interface WorkQueueQuery {
59
60
  created?: { end?: Date; start?: Date };
60
61
  types?: string[];
61
- status: WorkStatus[];
62
+ status?: WorkStatus[];
62
63
  queryString?: string;
63
64
  scheduled?: { end?: Date; start?: Date };
64
65
  }
@@ -162,7 +163,7 @@ const defaultSort: { key: string; value: SortDirection }[] = [
162
163
  { key: 'created', value: SortDirection.ASC },
163
164
  ];
164
165
 
165
- const normalizeWorkQueueAggregateResult = (data = []): WorkerReport[] => {
166
+ const normalizeWorkQueueAggregateResult = (data: mongodb.Document[] = []): WorkerReport[] => {
166
167
  const statusToFieldMap = {
167
168
  NEW: 'newCount',
168
169
  ALLOCATED: 'startCount',
@@ -204,7 +205,7 @@ export const configureWorkerModule = async ({ db, options }: ModuleInput<WorkerS
204
205
  }: {
205
206
  types: string[];
206
207
  worker: string;
207
- }): Promise<Work> => {
208
+ }) => {
208
209
  // Find a work item that is scheduled for now and is not started.
209
210
  // Also:
210
211
  // - Restrict by types and worker if provided
@@ -223,10 +224,8 @@ export const configureWorkerModule = async ({ db, options }: ModuleInput<WorkerS
223
224
  { sort: buildSortOptions(defaultSort), returnDocument: 'after' },
224
225
  );
225
226
 
226
- if (result) {
227
- emit(WorkerEventTypes.ALLOCATED, removePrivateFields(result));
228
- }
229
-
227
+ if (!result) return null;
228
+ emit(WorkerEventTypes.ALLOCATED, removePrivateFields(result));
230
229
  return result;
231
230
  };
232
231
 
@@ -244,7 +243,7 @@ export const configureWorkerModule = async ({ db, options }: ModuleInput<WorkerS
244
243
  started?: Date;
245
244
  worker?: string;
246
245
  },
247
- ): Promise<Work> => {
246
+ ) => {
248
247
  const workBeforeUpdate = await WorkQueue.findOne(
249
248
  buildQuerySelector({ workId, status: [WorkStatus.ALLOCATED] }),
250
249
  );
@@ -267,7 +266,9 @@ export const configureWorkerModule = async ({ db, options }: ModuleInput<WorkerS
267
266
  { returnDocument: 'after' },
268
267
  );
269
268
 
270
- const duration = new Date(work.finished).getTime() - new Date(work.started).getTime();
269
+ if (!work) return null;
270
+
271
+ const duration = new Date(work.finished!).getTime() - new Date(work.started!).getTime();
271
272
  if (work.success) {
272
273
  logger.debug(`${work.type} finished with success (${duration}ms)`, {
273
274
  workId,
@@ -295,14 +296,20 @@ export const configureWorkerModule = async ({ db, options }: ModuleInput<WorkerS
295
296
  return typeList.map((t) => t._id as string);
296
297
  },
297
298
 
298
- findWork: async ({
299
- workId,
300
- originalWorkId,
301
- }: {
302
- workId?: string;
303
- originalWorkId?: string;
304
- }): Promise<Work> =>
305
- WorkQueue.findOne(workId ? generateDbFilterById(workId) : { originalWorkId }, {}),
299
+ findWork: async (
300
+ params:
301
+ | {
302
+ workId: string;
303
+ }
304
+ | {
305
+ originalWorkId: string;
306
+ },
307
+ ) => {
308
+ if ('workId' in params) {
309
+ return WorkQueue.findOne(generateDbFilterById(params.workId), {});
310
+ }
311
+ return WorkQueue.findOne({ originalWorkId: params.originalWorkId }, {});
312
+ },
306
313
 
307
314
  findWorkQueue: async ({
308
315
  limit,
@@ -397,7 +404,7 @@ export const configureWorkerModule = async ({ db, options }: ModuleInput<WorkerS
397
404
  },
398
405
 
399
406
  // Mutations
400
- addWork: async ({
407
+ async addWork({
401
408
  type,
402
409
  input,
403
410
  priority = 0,
@@ -405,13 +412,14 @@ export const configureWorkerModule = async ({ db, options }: ModuleInput<WorkerS
405
412
  originalWorkId,
406
413
  worker = null,
407
414
  retries = 20,
408
- }: WorkData): Promise<Work> => {
415
+ }: Pick<Work, 'type' | 'originalWorkId' | 'worker'> &
416
+ Pick<Partial<Work>, 'scheduled' | 'priority' | 'input' | 'retries'>): Promise<Work> {
409
417
  const created = new Date();
410
418
  const { insertedId: workId } = await WorkQueue.insertOne({
411
419
  _id: generateDbObjectId(),
412
420
  created,
413
421
  type,
414
- input,
422
+ input: input || {},
415
423
  priority,
416
424
  scheduled: scheduled || created,
417
425
  originalWorkId,
@@ -423,13 +431,13 @@ export const configureWorkerModule = async ({ db, options }: ModuleInput<WorkerS
423
431
  workId,
424
432
  });
425
433
 
426
- const work = await WorkQueue.findOne(generateDbFilterById(workId), {});
434
+ const work = (await WorkQueue.findOne(generateDbFilterById(workId), {})) as Work;
427
435
  emit(WorkerEventTypes.ADDED, removePrivateFields(work));
428
436
 
429
437
  return work;
430
438
  },
431
439
 
432
- rescheduleWork: async (currentWork: Work, scheduled: Date): Promise<Work> => {
440
+ rescheduleWork: async (currentWork: Work, scheduled: Date) => {
433
441
  const work = await WorkQueue.findOneAndUpdate(
434
442
  generateDbFilterById(currentWork._id),
435
443
  {
@@ -441,6 +449,7 @@ export const configureWorkerModule = async ({ db, options }: ModuleInput<WorkerS
441
449
  { returnDocument: 'after' },
442
450
  );
443
451
 
452
+ if (!work) return null;
444
453
  emit(WorkerEventTypes.RESCHEDULED, {
445
454
  work: removePrivateFields(work),
446
455
  oldScheduled: currentWork.scheduled,
@@ -484,7 +493,7 @@ export const configureWorkerModule = async ({ db, options }: ModuleInput<WorkerS
484
493
  originalWorkId,
485
494
  retries = 20,
486
495
  scheduleId,
487
- }: WorkData): Promise<Work> => {
496
+ }: WorkData) => {
488
497
  const workId = `${scheduleId}:${scheduled.getTime()}`;
489
498
 
490
499
  const created = new Date();
@@ -528,7 +537,7 @@ export const configureWorkerModule = async ({ db, options }: ModuleInput<WorkerS
528
537
  },
529
538
  );
530
539
 
531
- if (!result.lastErrorObject.updatedExisting) {
540
+ if (!result.lastErrorObject) {
532
541
  logger.debug(`${type} auto-scheduled @ ${new Date(scheduled).toISOString()}`, {
533
542
  workId,
534
543
  });
@@ -547,7 +556,7 @@ export const configureWorkerModule = async ({ db, options }: ModuleInput<WorkerS
547
556
 
548
557
  finishWork,
549
558
 
550
- deleteWork: async (workId: string): Promise<Work> => {
559
+ deleteWork: async (workId: string) => {
551
560
  const workBeforeRemoval = await WorkQueue.findOne(
552
561
  buildQuerySelector({
553
562
  workId,
@@ -566,8 +575,8 @@ export const configureWorkerModule = async ({ db, options }: ModuleInput<WorkerS
566
575
  { returnDocument: 'after' },
567
576
  );
568
577
 
578
+ if (!work) return null;
569
579
  emit(WorkerEventTypes.DELETED, removePrivateFields(work));
570
-
571
580
  return work;
572
581
  },
573
582
 
@@ -590,21 +599,23 @@ export const configureWorkerModule = async ({ db, options }: ModuleInput<WorkerS
590
599
  { projection: { _id: true }, sort: { test: 1 } },
591
600
  ).toArray();
592
601
 
593
- return Promise.all(
594
- workQueue.map(({ _id }) =>
595
- finishWork(_id as string, {
596
- finished: new Date(),
597
- result: null,
598
- success: false,
599
- error: {
600
- name: DIRECTOR_MARKED_FAILED_ERROR,
601
- message:
602
- 'Director marked old work as failed after restart. This work was eventually running at the moment when node.js exited.',
603
- },
604
- worker,
605
- }),
606
- ),
607
- );
602
+ return (
603
+ await Promise.all(
604
+ workQueue.map(({ _id }) =>
605
+ finishWork(_id as string, {
606
+ finished: new Date(),
607
+ result: null,
608
+ success: false,
609
+ error: {
610
+ name: DIRECTOR_MARKED_FAILED_ERROR,
611
+ message:
612
+ 'Director marked old work as failed after restart. This work was eventually running at the moment when node.js exited.',
613
+ },
614
+ worker,
615
+ }),
616
+ ),
617
+ )
618
+ ).filter(Boolean) as Work[];
608
619
  },
609
620
 
610
621
  getReport: async ({
@@ -614,13 +625,13 @@ export const configureWorkerModule = async ({ db, options }: ModuleInput<WorkerS
614
625
  types?: string[];
615
626
  dateRange?: DateFilterInput;
616
627
  }): Promise<WorkerReport[]> => {
617
- const pipeline = [];
618
- const matchConditions = [];
628
+ const pipeline: mongodb.BSON.Document[] = [];
629
+ const matchConditions: any[] = [];
619
630
  // build date filter based on provided values it can be a range if both to and from is supplied
620
631
  // a upper or lowe limit if either from or to is provided
621
632
  // or all if none is provided
622
633
  if (dateRange?.start || dateRange?.end) {
623
- const dateConditions = [];
634
+ const dateConditions: any[] = [];
624
635
  if (dateRange?.start) {
625
636
  const fromDate = new Date(dateRange?.start);
626
637
  dateConditions.push({
package/tsconfig.json CHANGED
@@ -3,7 +3,8 @@
3
3
  "compilerOptions": {
4
4
  "declarationDir": "./lib",
5
5
  "rootDir": "./src",
6
- "outDir": "./lib"
6
+ "outDir": "./lib",
7
+
7
8
  },
8
9
  "exclude": ["**/*.test.ts", "**/*.test.js", "tests", "lib"]
9
10
  }