@wabot-dev/framework 0.4.0-beta.2 → 0.4.0-beta.4
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/src/_virtual/CronDate.js +3 -0
- package/dist/src/_virtual/CronDayOfMonth.js +3 -0
- package/dist/src/_virtual/CronDayOfWeek.js +3 -0
- package/dist/src/_virtual/CronExpression.js +3 -0
- package/dist/src/_virtual/CronExpressionParser.js +3 -0
- package/dist/src/_virtual/CronField.js +3 -0
- package/dist/src/_virtual/CronFieldCollection.js +3 -0
- package/dist/src/_virtual/CronFileParser.js +3 -0
- package/dist/src/_virtual/CronHour.js +3 -0
- package/dist/src/_virtual/CronMinute.js +3 -0
- package/dist/src/_virtual/CronMonth.js +3 -0
- package/dist/src/_virtual/CronSecond.js +3 -0
- package/dist/src/_virtual/index.js +5 -0
- package/dist/src/_virtual/index2.js +3 -0
- package/dist/src/_virtual/index3.js +3 -0
- package/dist/src/_virtual/luxon.js +3 -0
- package/dist/src/_virtual/random.js +3 -0
- package/dist/src/_virtual/types.js +3 -0
- package/dist/src/addon/async/pg/PgCronJobRepository.js +49 -0
- package/dist/src/addon/async/pg/PgJobRepository.js +2 -0
- package/dist/src/feature/async/@cron.js +17 -0
- package/dist/src/feature/async/CronJob.js +67 -0
- package/dist/src/feature/async/CronJobRepository.js +19 -0
- package/dist/src/feature/async/CronScheduler.js +165 -0
- package/dist/src/feature/async/runCronHandlers.js +18 -0
- package/dist/src/index.d.ts +62 -1
- package/dist/src/index.js +5 -0
- package/dist/src/node_modules/cron-parser/dist/CronDate.js +510 -0
- package/dist/src/node_modules/cron-parser/dist/CronExpression.js +420 -0
- package/dist/src/node_modules/cron-parser/dist/CronExpressionParser.js +396 -0
- package/dist/src/node_modules/cron-parser/dist/CronFieldCollection.js +382 -0
- package/dist/src/node_modules/cron-parser/dist/CronFileParser.js +122 -0
- package/dist/src/node_modules/cron-parser/dist/fields/CronDayOfMonth.js +55 -0
- package/dist/src/node_modules/cron-parser/dist/fields/CronDayOfWeek.js +62 -0
- package/dist/src/node_modules/cron-parser/dist/fields/CronField.js +193 -0
- package/dist/src/node_modules/cron-parser/dist/fields/CronHour.js +51 -0
- package/dist/src/node_modules/cron-parser/dist/fields/CronMinute.js +51 -0
- package/dist/src/node_modules/cron-parser/dist/fields/CronMonth.js +56 -0
- package/dist/src/node_modules/cron-parser/dist/fields/CronSecond.js +51 -0
- package/dist/src/node_modules/cron-parser/dist/fields/index.js +44 -0
- package/dist/src/node_modules/cron-parser/dist/fields/types.js +12 -0
- package/dist/src/node_modules/cron-parser/dist/index.js +49 -0
- package/dist/src/node_modules/cron-parser/dist/utils/random.js +48 -0
- package/dist/src/node_modules/luxon/build/node/luxon.js +7802 -0
- package/package.json +1 -1
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { __decorate, __metadata } from 'tslib';
|
|
2
|
+
import { singleton } from '../../../core/injection/index.js';
|
|
3
|
+
import { CronJob } from '../../../feature/async/CronJob.js';
|
|
4
|
+
import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
|
|
5
|
+
import '../../../feature/pg/PgLock.js';
|
|
6
|
+
import 'debug';
|
|
7
|
+
import 'node:crypto';
|
|
8
|
+
import '../../../feature/pg/withPgClient.js';
|
|
9
|
+
import '../../../feature/pg/pgStorage.js';
|
|
10
|
+
import { Pool } from 'pg';
|
|
11
|
+
|
|
12
|
+
let PgCronJobRepository = class PgCronJobRepository extends PgCrudRepository {
|
|
13
|
+
constructor(pool) {
|
|
14
|
+
super(pool, {
|
|
15
|
+
schema: 'wabot',
|
|
16
|
+
table: 'cron_job',
|
|
17
|
+
constructor: CronJob,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
async findDue(date) {
|
|
21
|
+
date = date ?? new Date();
|
|
22
|
+
const sql = `
|
|
23
|
+
SELECT ${this.columns}
|
|
24
|
+
FROM ${this.table}
|
|
25
|
+
WHERE data ? 'nextRunAt'
|
|
26
|
+
AND (data->>'nextRunAt')::bigint <= $1
|
|
27
|
+
AND (data->>'enabled')::boolean
|
|
28
|
+
ORDER BY (data->>'nextRunAt')::bigint ASC
|
|
29
|
+
`;
|
|
30
|
+
const items = await this.query(sql, [date.getTime()]);
|
|
31
|
+
return items;
|
|
32
|
+
}
|
|
33
|
+
async findByName(name) {
|
|
34
|
+
const sql = `
|
|
35
|
+
SELECT ${this.columns}
|
|
36
|
+
FROM ${this.table}
|
|
37
|
+
WHERE data @> $1::jsonb
|
|
38
|
+
LIMIT 1
|
|
39
|
+
`;
|
|
40
|
+
const items = await this.query(sql, [JSON.stringify({ name })]);
|
|
41
|
+
return items[0] ?? null;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
PgCronJobRepository = __decorate([
|
|
45
|
+
singleton(),
|
|
46
|
+
__metadata("design:paramtypes", [Pool])
|
|
47
|
+
], PgCronJobRepository);
|
|
48
|
+
|
|
49
|
+
export { PgCronJobRepository };
|
|
@@ -9,11 +9,13 @@ import { withPgClient } from '../../../feature/pg/withPgClient.js';
|
|
|
9
9
|
import '../../../feature/pg/pgStorage.js';
|
|
10
10
|
import '../../../feature/async/AsyncMetadataStore.js';
|
|
11
11
|
import '../../../feature/async/Async.js';
|
|
12
|
+
import '../../../_virtual/index.js';
|
|
12
13
|
import { Job } from '../../../feature/async/Job.js';
|
|
13
14
|
import '../../../feature/async/JobRepository.js';
|
|
14
15
|
import '../../../feature/async/JobRunner.js';
|
|
15
16
|
import '../../../feature/async/JobScheduler.js';
|
|
16
17
|
import '../../../feature/async/JobWatchdog.js';
|
|
18
|
+
import '../../../feature/async/CronScheduler.js';
|
|
17
19
|
|
|
18
20
|
let PgJobRepository = class PgJobRepository extends PgCrudRepository {
|
|
19
21
|
constructor(pool) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AsyncMetadataStore } from './AsyncMetadataStore.js';
|
|
2
|
+
import { container, singleton } from '../../core/injection/index.js';
|
|
3
|
+
|
|
4
|
+
function cron(config) {
|
|
5
|
+
return function (target) {
|
|
6
|
+
const metadataStore = container.resolve(AsyncMetadataStore);
|
|
7
|
+
metadataStore.registerCron(target, {
|
|
8
|
+
name: config.name,
|
|
9
|
+
commandName: `cron:${config.name}`,
|
|
10
|
+
cron: config.cron,
|
|
11
|
+
enabled: !config.disabled,
|
|
12
|
+
});
|
|
13
|
+
singleton()(target);
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { cron };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { d as distExports } from '../../_virtual/index.js';
|
|
2
|
+
import { Entity } from '../../core/entity/Entity.js';
|
|
3
|
+
import { Job } from './Job.js';
|
|
4
|
+
|
|
5
|
+
class CronJob extends Entity {
|
|
6
|
+
constructor(data) {
|
|
7
|
+
super(data);
|
|
8
|
+
if (!data.nextRunAt) {
|
|
9
|
+
this.computeNextRun(new Date());
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
get nextRunAt() {
|
|
13
|
+
return this.data.nextRunAt ? new Date(this.data.nextRunAt) : null;
|
|
14
|
+
}
|
|
15
|
+
get lastRunAt() {
|
|
16
|
+
return this.data.lastRunAt ? new Date(this.data.lastRunAt) : null;
|
|
17
|
+
}
|
|
18
|
+
get maxConcurrency() {
|
|
19
|
+
return this.data.maxRunningJobs ?? 1;
|
|
20
|
+
}
|
|
21
|
+
get misfirePolicy() {
|
|
22
|
+
return this.data.misfirePolicy ?? 'RUN_ONCE';
|
|
23
|
+
}
|
|
24
|
+
get commandName() {
|
|
25
|
+
return this.data.commandName;
|
|
26
|
+
}
|
|
27
|
+
get name() {
|
|
28
|
+
return this.data.name;
|
|
29
|
+
}
|
|
30
|
+
isDue(now) {
|
|
31
|
+
if (!this.data.nextRunAt)
|
|
32
|
+
throw new Error(`CronJon with id = '${this.data.id}' nextRunAt is invalid`);
|
|
33
|
+
return this.data.enabled && this.data.nextRunAt <= now.getTime();
|
|
34
|
+
}
|
|
35
|
+
computeNextRun(from) {
|
|
36
|
+
const interval = distExports.CronExpressionParser.parse(this.data.cron, {
|
|
37
|
+
currentDate: from,
|
|
38
|
+
});
|
|
39
|
+
this.data.nextRunAt = interval.next().getTime();
|
|
40
|
+
}
|
|
41
|
+
markAsExecuted(at) {
|
|
42
|
+
this.data.lastRunAt = at.getTime();
|
|
43
|
+
this.computeNextRun(at);
|
|
44
|
+
}
|
|
45
|
+
nextJob() {
|
|
46
|
+
return new Job({
|
|
47
|
+
commandName: this.data.commandName,
|
|
48
|
+
commandData: this.data.commandData,
|
|
49
|
+
scheduledAt: this.data.nextRunAt,
|
|
50
|
+
reintentsDelaysInSeconds: this.data.reintentsDelaysInSeconds,
|
|
51
|
+
aceptableRunningTimeSeconds: this.data.aceptableRunningTimeSeconds,
|
|
52
|
+
stuckRetryAttempts: this.data.stuckRetryAttempts,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
validate() {
|
|
56
|
+
try {
|
|
57
|
+
distExports.CronExpressionParser.parse(this.data.cron);
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
throw new Error(`CronJob with id = '${this.data.id}' has invalid cron expression: ${this.data.cron}`);
|
|
61
|
+
}
|
|
62
|
+
if (!this.data.nextRunAt)
|
|
63
|
+
throw new Error(`CronJon with id = '${this.data.id}' nextRunAt is invalid`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { CronJob };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class CronJobRepository {
|
|
2
|
+
create(cronJob) {
|
|
3
|
+
throw new Error('Method not implemented.');
|
|
4
|
+
}
|
|
5
|
+
findByName(name) {
|
|
6
|
+
throw new Error('Method not implemented.');
|
|
7
|
+
}
|
|
8
|
+
update(cronJob) {
|
|
9
|
+
throw new Error('Method not implemented.');
|
|
10
|
+
}
|
|
11
|
+
findDue(date) {
|
|
12
|
+
throw new Error('Method not implemented.');
|
|
13
|
+
}
|
|
14
|
+
findOrThrow(id) {
|
|
15
|
+
throw new Error('Method not implemented.');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { CronJobRepository };
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { __decorate, __metadata } from 'tslib';
|
|
2
|
+
import { singleton } from '../../core/injection/index.js';
|
|
3
|
+
import { JobRepository } from './JobRepository.js';
|
|
4
|
+
import { Logger } from '../../core/logger/Logger.js';
|
|
5
|
+
import { CronJob } from './CronJob.js';
|
|
6
|
+
import { CronJobRepository } from './CronJobRepository.js';
|
|
7
|
+
import { JobScheduler } from './JobScheduler.js';
|
|
8
|
+
import { Locker } from '../../core/lock/Locker.js';
|
|
9
|
+
import { Env } from '../../core/env/Env.js';
|
|
10
|
+
import { JobWatchdog } from './JobWatchdog.js';
|
|
11
|
+
|
|
12
|
+
let CronScheduler = class CronScheduler {
|
|
13
|
+
locker;
|
|
14
|
+
cronRepo;
|
|
15
|
+
jobRepo;
|
|
16
|
+
jobScheduler;
|
|
17
|
+
jobWatchdog;
|
|
18
|
+
env;
|
|
19
|
+
running = false;
|
|
20
|
+
timeout;
|
|
21
|
+
configuredCrons = new Map();
|
|
22
|
+
logger = new Logger('wabot:cron-scheduler');
|
|
23
|
+
constructor(locker, cronRepo, jobRepo, jobScheduler, jobWatchdog, env) {
|
|
24
|
+
this.locker = locker;
|
|
25
|
+
this.cronRepo = cronRepo;
|
|
26
|
+
this.jobRepo = jobRepo;
|
|
27
|
+
this.jobScheduler = jobScheduler;
|
|
28
|
+
this.jobWatchdog = jobWatchdog;
|
|
29
|
+
this.env = env;
|
|
30
|
+
}
|
|
31
|
+
start(crons) {
|
|
32
|
+
crons.forEach((x) => this.configuredCrons.set(x.name, x));
|
|
33
|
+
if (this.configuredCrons.size > 0 && !this.running) {
|
|
34
|
+
this.running = true;
|
|
35
|
+
this.tick();
|
|
36
|
+
}
|
|
37
|
+
if (this.running)
|
|
38
|
+
this.reconciliation();
|
|
39
|
+
}
|
|
40
|
+
stop(crons) {
|
|
41
|
+
crons.forEach((x) => {
|
|
42
|
+
const configured = this.configuredCrons.get(x.name);
|
|
43
|
+
if (!configured) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (configured.reconciliated) {
|
|
47
|
+
this.jobScheduler.stop([configured.commandName]);
|
|
48
|
+
this.jobWatchdog.stop([configured.commandName]);
|
|
49
|
+
}
|
|
50
|
+
this.configuredCrons.delete(x.name);
|
|
51
|
+
});
|
|
52
|
+
if (this.configuredCrons.size === 0) {
|
|
53
|
+
this.running = false;
|
|
54
|
+
if (this.timeout)
|
|
55
|
+
clearTimeout(this.timeout);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async reconciliation() {
|
|
59
|
+
const configToReconciliate = Array.from(this.configuredCrons.values()).filter((x) => !x.reconciliated);
|
|
60
|
+
this.logger.debug(`start reconciliation of crons ${configToReconciliate.map((x) => x.name).join(', ')}`);
|
|
61
|
+
try {
|
|
62
|
+
const cronJobs = await Promise.all(configToReconciliate.map((x) => this.reconciliateConfig(x)));
|
|
63
|
+
this.logger.info(`success reconciliation of reconciliation of crons ${configToReconciliate.map((x) => x.name).join(', ')}`);
|
|
64
|
+
this.jobScheduler.start(cronJobs.map((x) => x.commandName));
|
|
65
|
+
this.jobWatchdog.start(cronJobs.map((x) => x.commandName));
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
this.logger.error(e);
|
|
69
|
+
this.stop(configToReconciliate);
|
|
70
|
+
this.logger.error(`reconciliation fail - stopped crons ${configToReconciliate.map((x) => x.name).join(', ')}`);
|
|
71
|
+
throw e;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async tick() {
|
|
75
|
+
if (!this.running)
|
|
76
|
+
return;
|
|
77
|
+
const interval = this.env.requireNumber('WABOT_CRON_SCHEDULER_INTERVAL_SECONDS', {
|
|
78
|
+
default: 30,
|
|
79
|
+
});
|
|
80
|
+
try {
|
|
81
|
+
await this.locker.withKey('wabot-cron-scheduler').run(async () => {
|
|
82
|
+
const now = new Date();
|
|
83
|
+
const dueCrons = await this.cronRepo.findDue(now);
|
|
84
|
+
const readyToRunCrons = dueCrons.filter((x) => x.isDue(now) && this.configuredCrons.get(x.name)?.reconciliated);
|
|
85
|
+
for (const cron of readyToRunCrons) {
|
|
86
|
+
await this.spawnJobs(cron);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
catch (e) {
|
|
91
|
+
this.logger.error(e);
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
this.timeout = setTimeout(() => this.tick(), interval * 1000);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async spawnJobs(cron) {
|
|
98
|
+
await this.locker.withKey(`wabot-cron-${cron.id}`).run(async () => {
|
|
99
|
+
let now = new Date();
|
|
100
|
+
const fresh = await this.cronRepo.findOrThrow(cron.id);
|
|
101
|
+
if (!fresh.isDue(now))
|
|
102
|
+
return;
|
|
103
|
+
// ---- Overlap prevention ----
|
|
104
|
+
const running = await this.jobRepo.countRunningByCommand(fresh.commandName);
|
|
105
|
+
if (running >= fresh.maxConcurrency) {
|
|
106
|
+
this.logger.debug(`Cron ${fresh.id} skipped (running ${running}/${fresh.maxConcurrency})`);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// ---- Misfire handling ----
|
|
110
|
+
now = new Date();
|
|
111
|
+
let executions = 0;
|
|
112
|
+
while (fresh.isDue(now)) {
|
|
113
|
+
executions++;
|
|
114
|
+
await this.jobRepo.create(fresh.nextJob());
|
|
115
|
+
fresh.markAsExecuted(now);
|
|
116
|
+
if (fresh.misfirePolicy === 'RUN_ONCE')
|
|
117
|
+
break;
|
|
118
|
+
if (fresh.misfirePolicy === 'SKIP') {
|
|
119
|
+
fresh.computeNextRun(now);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
// Safety guard (never infinite)
|
|
123
|
+
if (executions >= 10) {
|
|
124
|
+
this.logger.warn(`Cron ${fresh.id} reached max misfire executions`);
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
await this.cronRepo.update(fresh);
|
|
129
|
+
this.logger.info(`Cron ${fresh.id} spawned ${executions} job(s), next at ${fresh.nextRunAt.toISOString()}`);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
async reconciliateConfig(config) {
|
|
133
|
+
return await this.locker.withKey(`wabot-cron-config-${config.name}`).run(async () => {
|
|
134
|
+
let cronJob = await this.cronRepo.findByName(config.name);
|
|
135
|
+
if (cronJob) {
|
|
136
|
+
this.logger.debug(`found cron job for name='${config.name}'`);
|
|
137
|
+
cronJob.update({ cron: config.cron, enabled: config.enabled });
|
|
138
|
+
await this.cronRepo.update(cronJob);
|
|
139
|
+
this.logger.debug(`cron job for name='${config.name}' updated`);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
cronJob = new CronJob({
|
|
143
|
+
name: config.name,
|
|
144
|
+
cron: config.cron,
|
|
145
|
+
commandName: config.commandName,
|
|
146
|
+
enabled: config.enabled,
|
|
147
|
+
});
|
|
148
|
+
await this.cronRepo.create(cronJob);
|
|
149
|
+
}
|
|
150
|
+
config.reconciliated = true;
|
|
151
|
+
return cronJob;
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
CronScheduler = __decorate([
|
|
156
|
+
singleton(),
|
|
157
|
+
__metadata("design:paramtypes", [Locker,
|
|
158
|
+
CronJobRepository,
|
|
159
|
+
JobRepository,
|
|
160
|
+
JobScheduler,
|
|
161
|
+
JobWatchdog,
|
|
162
|
+
Env])
|
|
163
|
+
], CronScheduler);
|
|
164
|
+
|
|
165
|
+
export { CronScheduler };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { container } from '../../core/injection/index.js';
|
|
2
|
+
import { AsyncMetadataStore } from './AsyncMetadataStore.js';
|
|
3
|
+
import { CronScheduler } from './CronScheduler.js';
|
|
4
|
+
|
|
5
|
+
function runCronHandlers(handlers) {
|
|
6
|
+
const metadataStore = container.resolve(AsyncMetadataStore);
|
|
7
|
+
const cronScheduler = container.resolve(CronScheduler);
|
|
8
|
+
const cronsMetadata = handlers.map((x) => metadataStore.requireCronMetadata(x)).flat();
|
|
9
|
+
cronScheduler.start(cronsMetadata.map((x) => x.config));
|
|
10
|
+
}
|
|
11
|
+
function stopCronHandlers(handlers) {
|
|
12
|
+
const metadataStore = container.resolve(AsyncMetadataStore);
|
|
13
|
+
const cronScheduler = container.resolve(CronScheduler);
|
|
14
|
+
const cronsMetadata = handlers.map((x) => metadataStore.requireCronMetadata(x)).flat();
|
|
15
|
+
cronScheduler.stop(cronsMetadata.map((x) => x.config));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { runCronHandlers, stopCronHandlers };
|
package/dist/src/index.d.ts
CHANGED
|
@@ -372,6 +372,13 @@ interface ICronHandler {
|
|
|
372
372
|
handleError?(e: any): void | Promise<void>;
|
|
373
373
|
}
|
|
374
374
|
|
|
375
|
+
interface ICronConfig {
|
|
376
|
+
name: string;
|
|
377
|
+
cron: string;
|
|
378
|
+
disabled?: boolean;
|
|
379
|
+
}
|
|
380
|
+
declare function cron(config: ICronConfig): (target: IConstructor<ICronHandler>) => void;
|
|
381
|
+
|
|
375
382
|
interface ICronJobScheduleConfig {
|
|
376
383
|
name: string;
|
|
377
384
|
commandName: string;
|
|
@@ -508,9 +515,57 @@ declare class Async {
|
|
|
508
515
|
runCommand<T>(ctor: IConstructor<T>, data: IValidateInputShape<T>): Promise<Job>;
|
|
509
516
|
}
|
|
510
517
|
|
|
518
|
+
interface ICronJobData extends IEntityData {
|
|
519
|
+
name: string;
|
|
520
|
+
commandName: string;
|
|
521
|
+
commandData?: object;
|
|
522
|
+
cron: string;
|
|
523
|
+
enabled: boolean;
|
|
524
|
+
lastRunAt?: number;
|
|
525
|
+
nextRunAt?: number;
|
|
526
|
+
maxRunningJobs?: number;
|
|
527
|
+
misfirePolicy?: 'RUN_ONCE' | 'RUN_ALL' | 'SKIP';
|
|
528
|
+
reintentsDelaysInSeconds?: number[];
|
|
529
|
+
aceptableRunningTimeSeconds?: number;
|
|
530
|
+
stuckRetryAttempts?: number;
|
|
531
|
+
}
|
|
532
|
+
declare class CronJob extends Entity<ICronJobData> {
|
|
533
|
+
constructor(data: ICronJobData);
|
|
534
|
+
get nextRunAt(): Date | null;
|
|
535
|
+
get lastRunAt(): Date | null;
|
|
536
|
+
get maxConcurrency(): number;
|
|
537
|
+
get misfirePolicy(): "RUN_ONCE" | "RUN_ALL" | "SKIP";
|
|
538
|
+
get commandName(): string;
|
|
539
|
+
get name(): string;
|
|
540
|
+
isDue(now: Date): boolean;
|
|
541
|
+
computeNextRun(from: Date): void;
|
|
542
|
+
markAsExecuted(at: Date): void;
|
|
543
|
+
nextJob(): Job;
|
|
544
|
+
validate(): void;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
interface ICronJobRepository {
|
|
548
|
+
create(cronJob: CronJob): Promise<void>;
|
|
549
|
+
findDue(date?: Date): Promise<CronJob[]>;
|
|
550
|
+
findOrThrow(id: string): Promise<CronJob>;
|
|
551
|
+
update(cronJob: CronJob): Promise<void>;
|
|
552
|
+
findByName(name: string): Promise<CronJob | null>;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
declare class CronJobRepository implements ICronJobRepository {
|
|
556
|
+
create(cronJob: CronJob): Promise<void>;
|
|
557
|
+
findByName(name: string): Promise<CronJob | null>;
|
|
558
|
+
update(cronJob: CronJob): Promise<void>;
|
|
559
|
+
findDue(date?: Date): Promise<CronJob[]>;
|
|
560
|
+
findOrThrow(id: string): Promise<CronJob>;
|
|
561
|
+
}
|
|
562
|
+
|
|
511
563
|
declare function runCommandHandlers(handlers: IConstructor<ICommandHandler<any>>[]): void;
|
|
512
564
|
declare function stopCommandHandlers(handlers: IConstructor<ICommandHandler<any>>[]): void;
|
|
513
565
|
|
|
566
|
+
declare function runCronHandlers(handlers: IConstructor<ICronHandler>[]): void;
|
|
567
|
+
declare function stopCronHandlers(handlers: IConstructor<ICronHandler>[]): void;
|
|
568
|
+
|
|
514
569
|
interface IChatConnection {
|
|
515
570
|
chatType: 'GROUP' | 'PRIVATE';
|
|
516
571
|
channelName: string;
|
|
@@ -1133,6 +1188,12 @@ declare class PgJobRepository extends PgCrudRepository<Job> implements IJobRepos
|
|
|
1133
1188
|
countRunningByCommand(commandName: string): Promise<number>;
|
|
1134
1189
|
}
|
|
1135
1190
|
|
|
1191
|
+
declare class PgCronJobRepository extends PgCrudRepository<CronJob> implements ICronJobRepository {
|
|
1192
|
+
constructor(pool: Pool);
|
|
1193
|
+
findDue(date?: Date): Promise<CronJob[]>;
|
|
1194
|
+
findByName(name: string): Promise<CronJob | null>;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1136
1197
|
declare function apiKeyHandshakeGuard(): (target: IConstructor<any>) => void;
|
|
1137
1198
|
|
|
1138
1199
|
declare function apiKeyGuard(): (target: object, propertyKey: string | symbol) => void;
|
|
@@ -1785,4 +1846,4 @@ declare function HtmlModule(options: IHtmlModuleOptions): {
|
|
|
1785
1846
|
new (): {};
|
|
1786
1847
|
};
|
|
1787
1848
|
|
|
1788
|
-
export { AnthropicChatAdapter, ApiKey, ApiKeyGuardMiddleware, ApiKeyHandshakeGuardMiddleware, ApiKeyRepository, Async, AsyncMetadataStore, Auth, Chat, ChatAdapter, ChatBot, ChatBotMetadataStore, ChatItem, ChatMemory, ChatRepository, ChatResolver, type ClientMap, CmdChannel, Container, ControllerMetadataStore, CustomError, DeepSeekChatAdapter, DescriptionMetadataStore, EXPRESS_REQ, EXPRESS_RES, Entity, Env, EnvWhatsAppRepository, ExpressProvider, GoogleChatAdapter, type GoogleChatAdapterV2Options, HtmlModule, HttpServerProvider, type IApiKeyData, type IApiKeyRepository, type IArrayValidationError, type IArrayValidationResult, type IBotMessageItem, type IChannelMessage, type IChannelMetadata, type IChatAdapter, type IChatAdapterNextItemsReq, type IChatAdapterNextItemsRes, type IChatBot, type IChatBotMetadata, type IChatChannel, type IChatConnection, type IChatControllerMetadata, type IChatData, type IChatItem, type IChatItemData, type IChatItemType, type IChatMemory, type IChatMessage, type IChatRepository, type IChatType, type ICommandConfig, type ICommandHandler, type ICommandHandlerConfig, type IConstructor, type ICrudRepository, type ICustomErrorData, type IDescriptionMetadata, type IEndPointConfig, type IEndPointMetadata, type IEntityData, type IEnvType, type IFunctionCall, type IFunctionCallItem, type IGenerateApiKeyReq, type IGenerateApiKeyRes, type IGetWhatsAppTemplateRequest, type IHandshakeMiddleware, type IHandshakeMiddlewareMetadata, type IHtmlModuleOptions, type IHumanMessageItem, type IJobData, type IJobRepository, type IJwtRefreshTokenData, type IJwtRefreshTokenRepository, type ILanguageModelUsage, type IListenWhatsAppMessageRequest, type ILockKey, type ILocker, type IMessageContext, type IMiddleware, type IMiddlewareMetadata, type IMindset, type IMindsetConfig, type IMindsetIdentity, type IMindsetLlm, type IMindsetMetadata, type IMindsetModuleConfig, type IMindsetModuleMetadata, type IMindsetTool, type IMindsetToolParameter, type IModelValidationError, type IModelValidationResult, type IModelValidatorsInfo, type IMoneyData, type IPersistentData, type IPgRepositoryConfig, type IPropertyValidatorInfo, type IReceivedMessage, type IRemoteApiKeyFetcher, type IRestControllerConfig, type IRestControllerMetadata, type ISendWhatsAppRequest, type ISendWhatsAppTemplateRequest, type ISocketChannelConfig, type ISocketChannelReceivedMessage, type ISocketControllerConfig, type ISocketControllerMetadata, type ISocketEventConfig, type ISocketEventMetadata, type IStorableData, type ITelegramChannelConfig, type IValidateArrayOptions, type IValidateArrayOptionsWithItemsValidators, type IValidateInputShape, type IValidateIsInOptions, type IValidateIsRecordOptions, type IValidateMaxOptions, type IValidateMinOptions, type IValidationError, type IValidationResult, type IValidator, type IValidatorMetadata, type IWhatsAppBusinessAccount, type IWhatsAppBusinessNumber, type IWhatsAppCloudContact, type IWhatsAppCloudMessage, type IWhatsAppCloudMessageMetadata, type IWhatsAppCloudTemplate, type IWhatsAppCloudTemplateComponent, type IWhatsAppCloudTemplateMessage, type IWhatsAppCloudTemplateParameter, type IWhatsAppCloudTemplateResponse, type IWhatsAppCloudWebhookPayload, type IWhatsAppData, type IWhatsAppMessageListener, type IWhatsAppProxyListenMessageEventData, type IWhatsAppProxyListenMessageEventReq, type IWhatsAppProxyMessage, type IWhatsAppProxyMessageContent, type IWhatsAppProxyMessageEventReq, type IWhatsAppProxySendMessageEventReq, type IWhatsAppRepository, type IWhatsAppSenderOptions, type IWhatsappChannelConfig, type IchatControllerConfig, Job, JobRepository, JobRunner, Jwt, JwtAccessAndRefreshTokenDto, JwtConfig, JwtGuardMiddleware, JwtHandshakeGuardMiddleware, JwtRefreshToken, JwtRefreshTokenRepository, JwtSigner, JwtTokenDto, Lifecycle, Locker, Logger, Mapper, Mindset, MindsetMetadataStore, MindsetOperator, Money, MoneyDto, OpenaiChatAdapter, Password, type PasswordHashOptions, Persistent, PgApiKeyRepository, PgChatMemory, PgChatRepository, PgCrudRepository, PgJobRepository, PgJwtRefreshTokenRepository, PgLockKey, PgLocker, PgRepositoryBase, PgWhatsAppRepository, RamChatMemory, RamChatRepository, Random, RemoteApiKeyRepository, RestControllerMetadataStore, RestRequest, SocketChannel, SocketChannelConfig, SocketChannelReceivedMessage, SocketControllerMetadataStore, SocketServerProvider, Storable, TelegramChannel, TelegramChannelConfig, ValidationMetadataStore, WHATSAPP_MESSAGE_EVENT, WHATSAPP_PROXY_LISTEN_MESSAGE_EVENT, WHATSAPP_PROXY_SEND_MESSAGE_EVENT, WabotChatAdapter, WhatsApp, WhatsAppChannel, WhatsAppReceiver, WhatsAppReceiverByCloudApi, WhatsAppReceiverByWabotProxy, WhatsAppRepository, WhatsAppSender, WhatsAppSenderByCloudApi, WhatsAppSenderByWabotProxy, WhatsAppWabotProxyConnection, WhatsappChannelConfig, apiKeyGuard, apiKeyHandshakeGuard, chatBot, chatController, chatItemTypeOptions, cmd, command, commandHandler, container, description, getClientMap, getPgClient, handshakeMiddlewares, inject, injectable, isArray, isBoolean, isDate, isIn, isModel, isNotEmpty, isNumber, isOptional, isPresent, isRecord, isString, jwtGuard, jwtHandshakeGuard, max, middleware, min, mindset, mindsetModule, modelInfo, onDelete, onGet, onPost, onPut, onSocketEvent, pgStorage, readJsonFromFile, restController, runChatControllers, runCommandHandlers, runRestControllers, runSocketControllers, scoped, singleton, socket, socketController, stopCommandHandlers, telegram, validateAndTransform, validateArray, validateIsBoolean, validateIsDate, validateIsIn, validateIsNotEmpty, validateIsNumber, validateIsPresent, validateIsRecord, validateIsString, validateMax, validateMin, validateModel, whatsApp, withPgClient, withPgTransaction, writeJsonToFile };
|
|
1849
|
+
export { AnthropicChatAdapter, ApiKey, ApiKeyGuardMiddleware, ApiKeyHandshakeGuardMiddleware, ApiKeyRepository, Async, AsyncMetadataStore, Auth, Chat, ChatAdapter, ChatBot, ChatBotMetadataStore, ChatItem, ChatMemory, ChatRepository, ChatResolver, type ClientMap, CmdChannel, Container, ControllerMetadataStore, CronJob, CronJobRepository, CustomError, DeepSeekChatAdapter, DescriptionMetadataStore, EXPRESS_REQ, EXPRESS_RES, Entity, Env, EnvWhatsAppRepository, ExpressProvider, GoogleChatAdapter, type GoogleChatAdapterV2Options, HtmlModule, HttpServerProvider, type IApiKeyData, type IApiKeyRepository, type IArrayValidationError, type IArrayValidationResult, type IBotMessageItem, type IChannelMessage, type IChannelMetadata, type IChatAdapter, type IChatAdapterNextItemsReq, type IChatAdapterNextItemsRes, type IChatBot, type IChatBotMetadata, type IChatChannel, type IChatConnection, type IChatControllerMetadata, type IChatData, type IChatItem, type IChatItemData, type IChatItemType, type IChatMemory, type IChatMessage, type IChatRepository, type IChatType, type ICommandConfig, type ICommandHandler, type ICommandHandlerConfig, type IConstructor, type ICronConfig, type ICronJobData, type ICrudRepository, type ICustomErrorData, type IDescriptionMetadata, type IEndPointConfig, type IEndPointMetadata, type IEntityData, type IEnvType, type IFunctionCall, type IFunctionCallItem, type IGenerateApiKeyReq, type IGenerateApiKeyRes, type IGetWhatsAppTemplateRequest, type IHandshakeMiddleware, type IHandshakeMiddlewareMetadata, type IHtmlModuleOptions, type IHumanMessageItem, type IJobData, type IJobRepository, type IJwtRefreshTokenData, type IJwtRefreshTokenRepository, type ILanguageModelUsage, type IListenWhatsAppMessageRequest, type ILockKey, type ILocker, type IMessageContext, type IMiddleware, type IMiddlewareMetadata, type IMindset, type IMindsetConfig, type IMindsetIdentity, type IMindsetLlm, type IMindsetMetadata, type IMindsetModuleConfig, type IMindsetModuleMetadata, type IMindsetTool, type IMindsetToolParameter, type IModelValidationError, type IModelValidationResult, type IModelValidatorsInfo, type IMoneyData, type IPersistentData, type IPgRepositoryConfig, type IPropertyValidatorInfo, type IReceivedMessage, type IRemoteApiKeyFetcher, type IRestControllerConfig, type IRestControllerMetadata, type ISendWhatsAppRequest, type ISendWhatsAppTemplateRequest, type ISocketChannelConfig, type ISocketChannelReceivedMessage, type ISocketControllerConfig, type ISocketControllerMetadata, type ISocketEventConfig, type ISocketEventMetadata, type IStorableData, type ITelegramChannelConfig, type IValidateArrayOptions, type IValidateArrayOptionsWithItemsValidators, type IValidateInputShape, type IValidateIsInOptions, type IValidateIsRecordOptions, type IValidateMaxOptions, type IValidateMinOptions, type IValidationError, type IValidationResult, type IValidator, type IValidatorMetadata, type IWhatsAppBusinessAccount, type IWhatsAppBusinessNumber, type IWhatsAppCloudContact, type IWhatsAppCloudMessage, type IWhatsAppCloudMessageMetadata, type IWhatsAppCloudTemplate, type IWhatsAppCloudTemplateComponent, type IWhatsAppCloudTemplateMessage, type IWhatsAppCloudTemplateParameter, type IWhatsAppCloudTemplateResponse, type IWhatsAppCloudWebhookPayload, type IWhatsAppData, type IWhatsAppMessageListener, type IWhatsAppProxyListenMessageEventData, type IWhatsAppProxyListenMessageEventReq, type IWhatsAppProxyMessage, type IWhatsAppProxyMessageContent, type IWhatsAppProxyMessageEventReq, type IWhatsAppProxySendMessageEventReq, type IWhatsAppRepository, type IWhatsAppSenderOptions, type IWhatsappChannelConfig, type IchatControllerConfig, Job, JobRepository, JobRunner, Jwt, JwtAccessAndRefreshTokenDto, JwtConfig, JwtGuardMiddleware, JwtHandshakeGuardMiddleware, JwtRefreshToken, JwtRefreshTokenRepository, JwtSigner, JwtTokenDto, Lifecycle, Locker, Logger, Mapper, Mindset, MindsetMetadataStore, MindsetOperator, Money, MoneyDto, OpenaiChatAdapter, Password, type PasswordHashOptions, Persistent, PgApiKeyRepository, PgChatMemory, PgChatRepository, PgCronJobRepository, PgCrudRepository, PgJobRepository, PgJwtRefreshTokenRepository, PgLockKey, PgLocker, PgRepositoryBase, PgWhatsAppRepository, RamChatMemory, RamChatRepository, Random, RemoteApiKeyRepository, RestControllerMetadataStore, RestRequest, SocketChannel, SocketChannelConfig, SocketChannelReceivedMessage, SocketControllerMetadataStore, SocketServerProvider, Storable, TelegramChannel, TelegramChannelConfig, ValidationMetadataStore, WHATSAPP_MESSAGE_EVENT, WHATSAPP_PROXY_LISTEN_MESSAGE_EVENT, WHATSAPP_PROXY_SEND_MESSAGE_EVENT, WabotChatAdapter, WhatsApp, WhatsAppChannel, WhatsAppReceiver, WhatsAppReceiverByCloudApi, WhatsAppReceiverByWabotProxy, WhatsAppRepository, WhatsAppSender, WhatsAppSenderByCloudApi, WhatsAppSenderByWabotProxy, WhatsAppWabotProxyConnection, WhatsappChannelConfig, apiKeyGuard, apiKeyHandshakeGuard, chatBot, chatController, chatItemTypeOptions, cmd, command, commandHandler, container, cron, description, getClientMap, getPgClient, handshakeMiddlewares, inject, injectable, isArray, isBoolean, isDate, isIn, isModel, isNotEmpty, isNumber, isOptional, isPresent, isRecord, isString, jwtGuard, jwtHandshakeGuard, max, middleware, min, mindset, mindsetModule, modelInfo, onDelete, onGet, onPost, onPut, onSocketEvent, pgStorage, readJsonFromFile, restController, runChatControllers, runCommandHandlers, runCronHandlers, runRestControllers, runSocketControllers, scoped, singleton, socket, socketController, stopCommandHandlers, stopCronHandlers, telegram, validateAndTransform, validateArray, validateIsBoolean, validateIsDate, validateIsIn, validateIsNotEmpty, validateIsNumber, validateIsPresent, validateIsRecord, validateIsString, validateMax, validateMin, validateModel, whatsApp, withPgClient, withPgTransaction, writeJsonToFile };
|
package/dist/src/index.js
CHANGED
|
@@ -41,12 +41,16 @@ export { DescriptionMetadataStore } from './core/description/metadata/Descriptio
|
|
|
41
41
|
export { Locker } from './core/lock/Locker.js';
|
|
42
42
|
export { command } from './feature/async/@command.js';
|
|
43
43
|
export { commandHandler } from './feature/async/@commandHandler.js';
|
|
44
|
+
export { cron } from './feature/async/@cron.js';
|
|
44
45
|
export { Async } from './feature/async/Async.js';
|
|
45
46
|
export { AsyncMetadataStore } from './feature/async/AsyncMetadataStore.js';
|
|
47
|
+
export { CronJob } from './feature/async/CronJob.js';
|
|
48
|
+
export { CronJobRepository } from './feature/async/CronJobRepository.js';
|
|
46
49
|
export { Job } from './feature/async/Job.js';
|
|
47
50
|
export { JobRepository } from './feature/async/JobRepository.js';
|
|
48
51
|
export { JobRunner } from './feature/async/JobRunner.js';
|
|
49
52
|
export { runCommandHandlers, stopCommandHandlers } from './feature/async/runCommandHandlers.js';
|
|
53
|
+
export { runCronHandlers, stopCronHandlers } from './feature/async/runCronHandlers.js';
|
|
50
54
|
export { Chat } from './feature/chat-bot/Chat.js';
|
|
51
55
|
export { ChatAdapter } from './feature/chat-bot/ChatAdapter.js';
|
|
52
56
|
export { ChatBot } from './feature/chat-bot/ChatBot.js';
|
|
@@ -93,6 +97,7 @@ export { onSocketEvent } from './feature/socket-controller/metadata/@onSocketEve
|
|
|
93
97
|
export { SocketControllerMetadataStore } from './feature/socket-controller/metadata/SocketControllerMetadataStore.js';
|
|
94
98
|
export { runSocketControllers } from './feature/socket-controller/runSocketControllers.js';
|
|
95
99
|
export { PgJobRepository } from './addon/async/pg/PgJobRepository.js';
|
|
100
|
+
export { PgCronJobRepository } from './addon/async/pg/PgCronJobRepository.js';
|
|
96
101
|
export { apiKeyHandshakeGuard } from './addon/auth/api-key/@apiKeyHandshakeGuard.js';
|
|
97
102
|
export { apiKeyGuard } from './addon/auth/api-key/@apiKeyGuard.js';
|
|
98
103
|
export { ApiKey } from './addon/auth/api-key/ApiKey.js';
|