@lowerdeck/cron 1.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.
- package/.turbo/turbo-build.log +12 -0
- package/.turbo/turbo-test.log +11 -0
- package/README.md +69 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.module.js +2 -0
- package/dist/index.module.js.map +1 -0
- package/dist/index.umd.js +2 -0
- package/dist/index.umd.js.map +1 -0
- package/package.json +37 -0
- package/src/index.ts +63 -0
- package/tsconfig.json +11 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
|
|
2
|
+
[0m[2m[35m$[0m [2m[1mmicrobundle[0m
|
|
3
|
+
No name was provided for external module '@lowerdeck/redis' in output.globals – guessing 'redis'
|
|
4
|
+
[34mBuild "@lowerdeck/cron" to dist:[39m
|
|
5
|
+
[32m496 B[39m: [37mindex.cjs[39m.gz
|
|
6
|
+
[32m427 B[39m: [37mindex.cjs[39m.br
|
|
7
|
+
[32m441 B[39m: [37mindex.module.js[39m.gz
|
|
8
|
+
[32m381 B[39m: [37mindex.module.js[39m.br
|
|
9
|
+
[32m510 B[39m: [37mindex.module.js[39m.gz
|
|
10
|
+
[32m429 B[39m: [37mindex.module.js[39m.br
|
|
11
|
+
[32m594 B[39m: [37mindex.umd.js[39m.gz
|
|
12
|
+
[32m497 B[39m: [37mindex.umd.js[39m.br
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
[0m[2m[35m$[0m [2m[1mvitest run --passWithNoTests[0m
|
|
3
|
+
[?25l
|
|
4
|
+
[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90m/Users/tobias/code/metorial/metorial-enterprise/oss/src/packages/backend/cron[39m
|
|
5
|
+
|
|
6
|
+
No test files found, exiting with code 0
|
|
7
|
+
|
|
8
|
+
[2minclude: [22m[33m**/*.{test,spec}.?(c|m)[jt]s?(x)[39m
|
|
9
|
+
[2mexclude: [22m[33m**/node_modules/**[2m, [22m**/dist/**[2m, [22m**/cypress/**[2m, [22m**/.{idea,git,cache,output,temp}/**[2m, [22m**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*[39m
|
|
10
|
+
|
|
11
|
+
[?25h
|
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# `@lowerdeck/cron`
|
|
2
|
+
|
|
3
|
+
Distributed cron job scheduler using BullMQ and Redis. Schedule recurring tasks with cron expressions that run reliably across multiple instances.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @lowerdeck/cron
|
|
9
|
+
yarn add @lowerdeck/cron
|
|
10
|
+
bun add @lowerdeck/cron
|
|
11
|
+
pnpm add @lowerdeck/cron
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { createCron } from '@lowerdeck/cron';
|
|
18
|
+
|
|
19
|
+
// Create a cron job that runs every minute
|
|
20
|
+
const cronJob = createCron(
|
|
21
|
+
{
|
|
22
|
+
name: 'cleanup-task',
|
|
23
|
+
cron: '*/1 * * * *', // every minute
|
|
24
|
+
redisUrl: 'redis://localhost:6379'
|
|
25
|
+
},
|
|
26
|
+
async () => {
|
|
27
|
+
console.log('Running cleanup task');
|
|
28
|
+
// Your task logic here
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// Start the cron job
|
|
33
|
+
const processor = await cronJob.start();
|
|
34
|
+
|
|
35
|
+
// Later, stop the cron job
|
|
36
|
+
await processor.close();
|
|
37
|
+
|
|
38
|
+
// Run every day at midnight
|
|
39
|
+
const dailyJob = createCron(
|
|
40
|
+
{
|
|
41
|
+
name: 'daily-report',
|
|
42
|
+
cron: '0 0 * * *',
|
|
43
|
+
redisUrl: process.env.REDIS_URL
|
|
44
|
+
},
|
|
45
|
+
async () => {
|
|
46
|
+
await generateDailyReport();
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// Run every 15 minutes
|
|
51
|
+
const frequentJob = createCron(
|
|
52
|
+
{
|
|
53
|
+
name: 'sync-data',
|
|
54
|
+
cron: '*/15 * * * *',
|
|
55
|
+
redisUrl: process.env.REDIS_URL
|
|
56
|
+
},
|
|
57
|
+
async () => {
|
|
58
|
+
await syncDataFromAPI();
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## License
|
|
64
|
+
|
|
65
|
+
This project is licensed under the Apache License 2.0.
|
|
66
|
+
|
|
67
|
+
<div align="center">
|
|
68
|
+
<sub>Built with ❤️ by <a href="https://metorial.com">Metorial</a></sub>
|
|
69
|
+
</div>
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e=require("@lowerdeck/redis"),r=require("bullmq"),n=function(){var e;return(e=console).log.apply(e,["[CRON MANAGER]:"].concat([].slice.call(arguments)))},o=new Set;exports.createCron=function(t,c){if(o.has(t.name))throw new Error("Cron with name "+t.name+" already exists");var i=e.parseRedisUrl(t.redisUrl),a=new r.Queue(t.name,{connection:i,defaultJobOptions:{removeOnComplete:!0,removeOnFail:!0}});return{start:function(){try{return n("Starting cron job "+t.name+" to run every "+t.cron+" using bullmq"),Promise.resolve(a.upsertJobScheduler("cron",{pattern:t.cron},{opts:{removeDependencyOnFailure:!0,removeOnComplete:!0,removeOnFail:!0,keepLogs:0}})).then(function(){var e=new r.Worker(t.name,function(){try{return n("Running cron job "+t.name),Promise.resolve(c()).then(function(){})}catch(e){return Promise.reject(e)}},{connection:i});return{close:e.close.bind(e)}})}catch(e){return Promise.reject(e)}}}};
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["import { IQueueProcessor } from '@lowerdeck/queue';\nimport { parseRedisUrl } from '@lowerdeck/redis';\nimport { Queue, Worker } from 'bullmq';\n\nlet log = (...any: any[]) => console.log('[CRON MANAGER]:', ...any);\n\nlet seenNames = new Set<string>();\n\nexport let createCron = (\n opts: {\n name: string;\n cron: string;\n redisUrl: string;\n },\n handler: () => Promise<void>\n): IQueueProcessor => {\n if (seenNames.has(opts.name)) {\n throw new Error(`Cron with name ${opts.name} already exists`);\n }\n\n let connection = parseRedisUrl(opts.redisUrl);\n let queue = new Queue(opts.name, {\n connection,\n defaultJobOptions: {\n removeOnComplete: true,\n removeOnFail: true\n }\n });\n\n return {\n start: async () => {\n log(`Starting cron job ${opts.name} to run every ${opts.cron} using bullmq`);\n\n await queue.upsertJobScheduler(\n 'cron',\n {\n pattern: opts.cron\n },\n {\n opts: {\n removeDependencyOnFailure: true,\n removeOnComplete: true,\n removeOnFail: true,\n keepLogs: 0\n }\n }\n );\n\n let worker = new Worker(\n opts.name,\n async () => {\n log(`Running cron job ${opts.name}`);\n await handler();\n },\n { connection }\n );\n\n return {\n close: worker.close.bind(worker)\n };\n }\n };\n};\n"],"names":["log","_console","console","apply","concat","slice","call","arguments","seenNames","Set","opts","handler","has","name","Error","connection","parseRedisUrl","redisUrl","queue","Queue","defaultJobOptions","removeOnComplete","removeOnFail","start","cron","Promise","resolve","upsertJobScheduler","pattern","removeDependencyOnFailure","keepLogs","then","worker","Worker","e","reject","close","bind"],"mappings":"sDAIIA,EAAM,WAAH,IAAAC,EAAA,OAAsBA,EAAAC,SAAQF,IAAGG,MAAAF,EAAA,CAAC,mBAAiBG,OAAA,GAAAC,MAAAC,KAAAC,YAAS,EAE/DC,EAAY,IAAIC,uBAEI,SACtBC,EAKAC,GAEA,GAAIH,EAAUI,IAAIF,EAAKG,MACrB,UAAUC,MAAwBJ,kBAAAA,EAAKG,KAAqB,mBAG9D,IAAIE,EAAaC,EAAaA,cAACN,EAAKO,UAChCC,EAAQ,IAAIC,EAAKA,MAACT,EAAKG,KAAM,CAC/BE,WAAAA,EACAK,kBAAmB,CACjBC,kBAAkB,EAClBC,cAAc,KAIlB,MAAO,CACLC,MAAK,WAAA,IAC0E,OAA7EvB,EAAyBU,qBAAAA,EAAKG,KAAqBH,iBAAAA,EAAKc,sBAAqBC,QAAAC,QAEvER,EAAMS,mBACV,OACA,CACEC,QAASlB,EAAKc,MAEhB,CACEd,KAAM,CACJmB,2BAA2B,EAC3BR,kBAAkB,EAClBC,cAAc,EACdQ,SAAU,MAGfC,KAAA,WAED,IAAIC,EAAS,IAAIC,EAAAA,OACfvB,EAAKG,KACM,WAAA,IAC4B,OAArCb,EAAG,oBAAqBU,EAAKG,MAAQY,QAAAC,QAC/Bf,KAASoB,KACjB,WAAA,EAAA,CAAC,MAAAG,GAAAT,OAAAA,QAAAU,OAAAD,EAAA,CAAA,EACD,CAAEnB,WAAAA,IAGJ,MAAO,CACLqB,MAAOJ,EAAOI,MAAMC,KAAKL,GACzB,EACJ,CAAC,MAAAE,GAAA,OAAAT,QAAAU,OAAAD,EAAA,CAAA,EAEL"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAQnD,eAAO,IAAI,UAAU,GACnB,MAAM;IACJ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,EACD,SAAS,MAAM,OAAO,CAAC,IAAI,CAAC,KAC3B,eA+CF,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{parseRedisUrl as e}from"@lowerdeck/redis";import{Queue as n,Worker as r}from"bullmq";var o=function(){var e;return(e=console).log.apply(e,["[CRON MANAGER]:"].concat([].slice.call(arguments)))},t=new Set,c=function(c,i){if(t.has(c.name))throw new Error("Cron with name "+c.name+" already exists");var a=e(c.redisUrl),l=new n(c.name,{connection:a,defaultJobOptions:{removeOnComplete:!0,removeOnFail:!0}});return{start:function(){try{return o("Starting cron job "+c.name+" to run every "+c.cron+" using bullmq"),Promise.resolve(l.upsertJobScheduler("cron",{pattern:c.cron},{opts:{removeDependencyOnFailure:!0,removeOnComplete:!0,removeOnFail:!0,keepLogs:0}})).then(function(){var e=new r(c.name,function(){try{return o("Running cron job "+c.name),Promise.resolve(i()).then(function(){})}catch(e){return Promise.reject(e)}},{connection:a});return{close:e.close.bind(e)}})}catch(e){return Promise.reject(e)}}}};export{c as createCron};
|
|
2
|
+
//# sourceMappingURL=index.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.module.js","sources":["../src/index.ts"],"sourcesContent":["import { IQueueProcessor } from '@lowerdeck/queue';\nimport { parseRedisUrl } from '@lowerdeck/redis';\nimport { Queue, Worker } from 'bullmq';\n\nlet log = (...any: any[]) => console.log('[CRON MANAGER]:', ...any);\n\nlet seenNames = new Set<string>();\n\nexport let createCron = (\n opts: {\n name: string;\n cron: string;\n redisUrl: string;\n },\n handler: () => Promise<void>\n): IQueueProcessor => {\n if (seenNames.has(opts.name)) {\n throw new Error(`Cron with name ${opts.name} already exists`);\n }\n\n let connection = parseRedisUrl(opts.redisUrl);\n let queue = new Queue(opts.name, {\n connection,\n defaultJobOptions: {\n removeOnComplete: true,\n removeOnFail: true\n }\n });\n\n return {\n start: async () => {\n log(`Starting cron job ${opts.name} to run every ${opts.cron} using bullmq`);\n\n await queue.upsertJobScheduler(\n 'cron',\n {\n pattern: opts.cron\n },\n {\n opts: {\n removeDependencyOnFailure: true,\n removeOnComplete: true,\n removeOnFail: true,\n keepLogs: 0\n }\n }\n );\n\n let worker = new Worker(\n opts.name,\n async () => {\n log(`Running cron job ${opts.name}`);\n await handler();\n },\n { connection }\n );\n\n return {\n close: worker.close.bind(worker)\n };\n }\n };\n};\n"],"names":["log","_console","console","apply","concat","slice","call","arguments","seenNames","Set","createCron","opts","handler","has","name","Error","connection","parseRedisUrl","redisUrl","queue","Queue","defaultJobOptions","removeOnComplete","removeOnFail","start","cron","Promise","resolve","upsertJobScheduler","pattern","removeDependencyOnFailure","keepLogs","then","worker","Worker","e","reject","close","bind"],"mappings":"4FAIA,IAAIA,EAAM,WAAH,IAAAC,EAAA,OAAsBA,EAAAC,SAAQF,IAAGG,MAAAF,EAAA,CAAC,mBAAiBG,OAAA,GAAAC,MAAAC,KAAAC,YAAS,EAE/DC,EAAY,IAAIC,IAETC,EAAa,SACtBC,EAKAC,GAEA,GAAIJ,EAAUK,IAAIF,EAAKG,MACrB,UAAUC,MAAwBJ,kBAAAA,EAAKG,KAAqB,mBAG9D,IAAIE,EAAaC,EAAcN,EAAKO,UAChCC,EAAQ,IAAIC,EAAMT,EAAKG,KAAM,CAC/BE,WAAAA,EACAK,kBAAmB,CACjBC,kBAAkB,EAClBC,cAAc,KAIlB,MAAO,CACLC,MAAK,WAAA,IAC0E,OAA7ExB,EAAyBW,qBAAAA,EAAKG,KAAqBH,iBAAAA,EAAKc,sBAAqBC,QAAAC,QAEvER,EAAMS,mBACV,OACA,CACEC,QAASlB,EAAKc,MAEhB,CACEd,KAAM,CACJmB,2BAA2B,EAC3BR,kBAAkB,EAClBC,cAAc,EACdQ,SAAU,MAGfC,KAAA,WAED,IAAIC,EAAS,IAAIC,EACfvB,EAAKG,KACM,WAAA,IAC4B,OAArCd,EAAG,oBAAqBW,EAAKG,MAAQY,QAAAC,QAC/Bf,KAASoB,KACjB,WAAA,EAAA,CAAC,MAAAG,GAAAT,OAAAA,QAAAU,OAAAD,EAAA,CAAA,EACD,CAAEnB,WAAAA,IAGJ,MAAO,CACLqB,MAAOJ,EAAOI,MAAMC,KAAKL,GACzB,EACJ,CAAC,MAAAE,GAAA,OAAAT,QAAAU,OAAAD,EAAA,CAAA,EAEL"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports,require("@lowerdeck/redis"),require("bullmq")):"function"==typeof define&&define.amd?define(["exports","@lowerdeck/redis","bullmq"],n):n((e||self).cron={},e.redis,e.bullmq)}(this,function(e,n,r){var o=function(){var e;return(e=console).log.apply(e,["[CRON MANAGER]:"].concat([].slice.call(arguments)))},t=new Set;e.createCron=function(e,i){if(t.has(e.name))throw new Error("Cron with name "+e.name+" already exists");var c=n.parseRedisUrl(e.redisUrl),l=new r.Queue(e.name,{connection:c,defaultJobOptions:{removeOnComplete:!0,removeOnFail:!0}});return{start:function(){try{return o("Starting cron job "+e.name+" to run every "+e.cron+" using bullmq"),Promise.resolve(l.upsertJobScheduler("cron",{pattern:e.cron},{opts:{removeDependencyOnFailure:!0,removeOnComplete:!0,removeOnFail:!0,keepLogs:0}})).then(function(){var n=new r.Worker(e.name,function(){try{return o("Running cron job "+e.name),Promise.resolve(i()).then(function(){})}catch(e){return Promise.reject(e)}},{connection:c});return{close:n.close.bind(n)}})}catch(e){return Promise.reject(e)}}}}});
|
|
2
|
+
//# sourceMappingURL=index.umd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/index.ts"],"sourcesContent":["import { IQueueProcessor } from '@lowerdeck/queue';\nimport { parseRedisUrl } from '@lowerdeck/redis';\nimport { Queue, Worker } from 'bullmq';\n\nlet log = (...any: any[]) => console.log('[CRON MANAGER]:', ...any);\n\nlet seenNames = new Set<string>();\n\nexport let createCron = (\n opts: {\n name: string;\n cron: string;\n redisUrl: string;\n },\n handler: () => Promise<void>\n): IQueueProcessor => {\n if (seenNames.has(opts.name)) {\n throw new Error(`Cron with name ${opts.name} already exists`);\n }\n\n let connection = parseRedisUrl(opts.redisUrl);\n let queue = new Queue(opts.name, {\n connection,\n defaultJobOptions: {\n removeOnComplete: true,\n removeOnFail: true\n }\n });\n\n return {\n start: async () => {\n log(`Starting cron job ${opts.name} to run every ${opts.cron} using bullmq`);\n\n await queue.upsertJobScheduler(\n 'cron',\n {\n pattern: opts.cron\n },\n {\n opts: {\n removeDependencyOnFailure: true,\n removeOnComplete: true,\n removeOnFail: true,\n keepLogs: 0\n }\n }\n );\n\n let worker = new Worker(\n opts.name,\n async () => {\n log(`Running cron job ${opts.name}`);\n await handler();\n },\n { connection }\n );\n\n return {\n close: worker.close.bind(worker)\n };\n }\n };\n};\n"],"names":["log","_console","console","apply","concat","slice","call","arguments","seenNames","Set","opts","handler","has","name","Error","connection","parseRedisUrl","redisUrl","queue","Queue","defaultJobOptions","removeOnComplete","removeOnFail","start","cron","Promise","resolve","upsertJobScheduler","pattern","removeDependencyOnFailure","keepLogs","then","worker","Worker","e","reject","close","bind"],"mappings":"6TAIA,IAAIA,EAAM,WAAH,IAAAC,EAAA,OAAsBA,EAAAC,SAAQF,IAAGG,MAAAF,EAAA,CAAC,mBAAiBG,OAAA,GAAAC,MAAAC,KAAAC,YAAS,EAE/DC,EAAY,IAAIC,iBAEI,SACtBC,EAKAC,GAEA,GAAIH,EAAUI,IAAIF,EAAKG,MACrB,UAAUC,MAAwBJ,kBAAAA,EAAKG,KAAqB,mBAG9D,IAAIE,EAAaC,EAAaA,cAACN,EAAKO,UAChCC,EAAQ,IAAIC,EAAKA,MAACT,EAAKG,KAAM,CAC/BE,WAAAA,EACAK,kBAAmB,CACjBC,kBAAkB,EAClBC,cAAc,KAIlB,MAAO,CACLC,MAAK,WAAA,IAC0E,OAA7EvB,EAAyBU,qBAAAA,EAAKG,KAAqBH,iBAAAA,EAAKc,sBAAqBC,QAAAC,QAEvER,EAAMS,mBACV,OACA,CACEC,QAASlB,EAAKc,MAEhB,CACEd,KAAM,CACJmB,2BAA2B,EAC3BR,kBAAkB,EAClBC,cAAc,EACdQ,SAAU,MAGfC,KAAA,WAED,IAAIC,EAAS,IAAIC,EAAAA,OACfvB,EAAKG,KACM,WAAA,IAC4B,OAArCb,EAAG,oBAAqBU,EAAKG,MAAQY,QAAAC,QAC/Bf,KAASoB,KACjB,WAAA,EAAA,CAAC,MAAAG,GAAAT,OAAAA,QAAAU,OAAAD,EAAA,CAAA,EACD,CAAEnB,WAAAA,IAGJ,MAAO,CACLqB,MAAOJ,EAAOI,MAAMC,KAAKL,GACzB,EACJ,CAAC,MAAAE,GAAA,OAAAT,QAAAU,OAAAD,EAAA,CAAA,EAEL"}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lowerdeck/cron",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"author": "Tobias Herber",
|
|
8
|
+
"license": "Apache 2",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"source": "src/index.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"require": "./dist/index.cjs",
|
|
14
|
+
"import": "./dist/index.module.js",
|
|
15
|
+
"default": "./dist/index.modern.js"
|
|
16
|
+
},
|
|
17
|
+
"main": "./dist/index.cjs",
|
|
18
|
+
"module": "./dist/index.module.js",
|
|
19
|
+
"types": "dist/index.d.ts",
|
|
20
|
+
"unpkg": "./dist/index.umd.js",
|
|
21
|
+
"scripts": {
|
|
22
|
+
"test": "vitest run --passWithNoTests",
|
|
23
|
+
"lint": "prettier src/**/*.ts --check",
|
|
24
|
+
"build": "microbundle"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@lowerdeck/queue": "^1.0.0",
|
|
28
|
+
"@lowerdeck/redis": "^1.0.0",
|
|
29
|
+
"bullmq": "^5.34.3"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@lowerdeck/tsconfig": "^1.0.0",
|
|
33
|
+
"typescript": "5.8.2",
|
|
34
|
+
"microbundle": "^0.15.1",
|
|
35
|
+
"vitest": "^3.1.2"
|
|
36
|
+
}
|
|
37
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { IQueueProcessor } from '@lowerdeck/queue';
|
|
2
|
+
import { parseRedisUrl } from '@lowerdeck/redis';
|
|
3
|
+
import { Queue, Worker } from 'bullmq';
|
|
4
|
+
|
|
5
|
+
let log = (...any: any[]) => console.log('[CRON MANAGER]:', ...any);
|
|
6
|
+
|
|
7
|
+
let seenNames = new Set<string>();
|
|
8
|
+
|
|
9
|
+
export let createCron = (
|
|
10
|
+
opts: {
|
|
11
|
+
name: string;
|
|
12
|
+
cron: string;
|
|
13
|
+
redisUrl: string;
|
|
14
|
+
},
|
|
15
|
+
handler: () => Promise<void>
|
|
16
|
+
): IQueueProcessor => {
|
|
17
|
+
if (seenNames.has(opts.name)) {
|
|
18
|
+
throw new Error(`Cron with name ${opts.name} already exists`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let connection = parseRedisUrl(opts.redisUrl);
|
|
22
|
+
let queue = new Queue(opts.name, {
|
|
23
|
+
connection,
|
|
24
|
+
defaultJobOptions: {
|
|
25
|
+
removeOnComplete: true,
|
|
26
|
+
removeOnFail: true
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
start: async () => {
|
|
32
|
+
log(`Starting cron job ${opts.name} to run every ${opts.cron} using bullmq`);
|
|
33
|
+
|
|
34
|
+
await queue.upsertJobScheduler(
|
|
35
|
+
'cron',
|
|
36
|
+
{
|
|
37
|
+
pattern: opts.cron
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
opts: {
|
|
41
|
+
removeDependencyOnFailure: true,
|
|
42
|
+
removeOnComplete: true,
|
|
43
|
+
removeOnFail: true,
|
|
44
|
+
keepLogs: 0
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
let worker = new Worker(
|
|
50
|
+
opts.name,
|
|
51
|
+
async () => {
|
|
52
|
+
log(`Running cron job ${opts.name}`);
|
|
53
|
+
await handler();
|
|
54
|
+
},
|
|
55
|
+
{ connection }
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
close: worker.close.bind(worker)
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
};
|
package/tsconfig.json
ADDED