@clairejs/server 3.20.1 → 3.21.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/README.md CHANGED
@@ -1,7 +1,12 @@
1
1
  ## Change Log
2
2
 
3
- #### 3.20.1:
3
+ #### 3.21.0:
4
4
 
5
+ - simplify lambda job scheduler, remove job interval that is less than 60s
6
+
7
+ #### 3.20.2:
8
+
9
+ - fix redlock timeout issue
5
10
  - fix req not resolve leads to undefined request in DefaultHttpRequestHandler
6
11
  - fix concurrent transactions in updateRecords
7
12
  - update claire core, claire orm and fix returning
@@ -1,43 +1,17 @@
1
1
  import { AbstractLogger } from "@clairejs/core";
2
2
  import { AbstractDbAdapter, ITransaction } from "@clairejs/orm";
3
3
  import aws from "aws-sdk";
4
- import Redis from "ioredis";
5
4
  import { AbstractJobScheduler } from "./AbstractJobScheduler";
6
5
  import { JobInfo, ScheduledJob } from "./interfaces";
7
6
  export declare class AwsJobScheduler extends AbstractJobScheduler {
8
7
  protected readonly logger: AbstractLogger;
9
8
  protected readonly db: AbstractDbAdapter;
10
- protected readonly redisClient: Redis;
11
- protected readonly uniqueIdKey: string;
9
+ protected readonly uniqueJobIdFactory: () => string;
12
10
  protected readonly apiLambdaFunctionArn: string;
13
- protected readonly stepFunctionName: string;
14
- /**
15
- * This IAM role must have following permissions:
16
- * - trigger any state machine (for one minute rule - as we don't now the state machine ARN until auto creation)
17
- * - trigger lambda function specified in apiLambdaFunctionArn (so state machine can trigger API)
18
- *
19
- * In addition, the role which this API server assumes must have following permissions:
20
- * - create event bridge rules, describe rules, remove rule, list and create rule targets
21
- * - create state machines, list state machines
22
- */
23
- protected readonly iamRoleArn: string;
24
11
  protected readonly eventBusName: string;
25
12
  protected readonly jobNamePrefix: string;
26
- protected readonly oneMinuteRule: string;
27
13
  protected readonly eventbridge: aws.EventBridge;
28
- protected readonly stepfunctions: aws.StepFunctions;
29
- constructor(logger: AbstractLogger, db: AbstractDbAdapter, redisClient: Redis, uniqueIdKey: string, apiLambdaFunctionArn: string, stepFunctionName: string,
30
- /**
31
- * This IAM role must have following permissions:
32
- * - trigger any state machine (for one minute rule - as we don't now the state machine ARN until auto creation)
33
- * - trigger lambda function specified in apiLambdaFunctionArn (so state machine can trigger API)
34
- *
35
- * In addition, the role which this API server assumes must have following permissions:
36
- * - create event bridge rules, describe rules, remove rule, list and create rule targets
37
- * - create state machines, list state machines
38
- */
39
- iamRoleArn: string, eventBusName?: string, jobNamePrefix?: string, oneMinuteRule?: string);
40
- handleInterval(interval: number): Promise<void>;
14
+ constructor(logger: AbstractLogger, db: AbstractDbAdapter, uniqueJobIdFactory: () => string, apiLambdaFunctionArn: string, eventBusName?: string, jobNamePrefix?: string);
41
15
  handleCron(jobInfo: ScheduledJob): Promise<void>;
42
16
  protected afterJob(_job: ScheduledJob, _tx: ITransaction): Promise<void>;
43
17
  private generateCronFromTimestamp;
@@ -46,5 +20,4 @@ export declare class AwsJobScheduler extends AbstractJobScheduler {
46
20
  protected scheduleJob(jobInfo: JobInfo): Promise<string>;
47
21
  syncJobs(): Promise<void>;
48
22
  removeJob(jobId: string): Promise<void>;
49
- private checkIntervalScheduler;
50
23
  }
@@ -10,140 +10,25 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  import { AbstractLogger, Errors, LogContext } from "@clairejs/core";
11
11
  import { AbstractDbAdapter } from "@clairejs/orm";
12
12
  import aws from "aws-sdk";
13
- import Redis from "ioredis";
14
13
  import { AbstractJobScheduler } from "./AbstractJobScheduler";
15
- import { JobInterval } from "./interfaces";
16
- const gcdBetween = (a, b) => {
17
- const greater = a > b ? a : b;
18
- const smaller = a > b ? b : a;
19
- if (greater <= 0 || smaller <= 0) {
20
- return 1;
21
- }
22
- else if (greater % smaller === 0) {
23
- return smaller;
24
- }
25
- else {
26
- const result = Math.trunc(greater / smaller);
27
- return gcdBetween(smaller, greater - smaller * result);
28
- }
29
- };
30
- const gcdOf = (val, arr) => {
31
- if (!arr.length) {
32
- return val;
33
- }
34
- else {
35
- return gcdOf(gcdBetween(val, arr[0]), arr.slice(1));
36
- }
37
- };
38
- const getWaitExpression = (interval) => `Wait ${interval} seconds`;
39
- const oneMinuteFunctionFactory = (lambdaFunctionARN, intervals) => {
40
- //-- find most greatest common divisor of intervals
41
- let gcd = JobInterval.EVERY_30S;
42
- if (intervals.length) {
43
- //-- re-calculate gcd
44
- gcd = gcdOf(intervals[0], intervals.slice(1));
45
- if (gcd < JobInterval.EVERY_5S) {
46
- gcd = JobInterval.EVERY_5S;
47
- }
48
- }
49
- //-- create loop array
50
- const itemCount = Math.trunc(60 / gcd);
51
- const itemArray = [];
52
- for (let i = 0; i < itemCount; i++) {
53
- itemArray.push(i * gcd);
54
- }
55
- const definition = `
56
- {
57
- "StartAt": "Create items",
58
- "States": {
59
- "Create items": {
60
- "Type": "Pass",
61
- "Next": "Loop",
62
- "Result": ${JSON.stringify(itemArray)}
63
- },
64
- "Loop": {
65
- "Type": "Map",
66
- "End": true,
67
- "Iterator": {
68
- "StartAt": "${getWaitExpression(gcd)}",
69
- "States": {
70
- "${getWaitExpression(gcd)}": {
71
- "Type": "Wait",
72
- "Seconds": ${gcd},
73
- "Next": "Convert time to request object"
74
- },
75
- "Convert time to request object": {
76
- "Type": "Pass",
77
- "Next": "Lambda Invoke",
78
- "Result": {
79
- "requestContext": {
80
- "intervalScheduler": {
81
- "time": "$"
82
- }
83
- }
84
- }
85
- },
86
- "Lambda Invoke": {
87
- "Type": "Task",
88
- "Resource": "arn:aws:states:::lambda:invoke",
89
- "Parameters": {
90
- "Payload.$": "$",
91
- "FunctionName": "${lambdaFunctionARN}:$LATEST"
92
- },
93
- "End": true,
94
- "OutputPath": "$.Payload"
95
- }
96
- }
97
- },
98
- "MaxConcurrency": 1
99
- }
100
- },
101
- "Comment": "One minute loop to trigger lambda function"
102
- }
103
- `;
104
- return [gcd, definition];
105
- };
106
14
  let AwsJobScheduler = class AwsJobScheduler extends AbstractJobScheduler {
107
15
  logger;
108
16
  db;
109
- redisClient;
110
- uniqueIdKey;
17
+ uniqueJobIdFactory;
111
18
  apiLambdaFunctionArn;
112
- stepFunctionName;
113
- iamRoleArn;
114
19
  eventBusName;
115
20
  jobNamePrefix;
116
- oneMinuteRule;
117
21
  eventbridge = new aws.EventBridge();
118
- stepfunctions = new aws.StepFunctions({ apiVersion: "2016-11-23" });
119
- constructor(logger, db, redisClient, uniqueIdKey, apiLambdaFunctionArn, stepFunctionName,
120
- /**
121
- * This IAM role must have following permissions:
122
- * - trigger any state machine (for one minute rule - as we don't now the state machine ARN until auto creation)
123
- * - trigger lambda function specified in apiLambdaFunctionArn (so state machine can trigger API)
124
- *
125
- * In addition, the role which this API server assumes must have following permissions:
126
- * - create event bridge rules, describe rules, remove rule, list and create rule targets
127
- * - create state machines, list state machines
128
- */
129
- iamRoleArn, eventBusName = "default", jobNamePrefix = "claire-aws-job-", oneMinuteRule = "one-minute-step-function-trigger") {
22
+ constructor(logger, db, uniqueJobIdFactory,
23
+ //-- ARN of the API lambda function, following EventBrige permissions is required: listRules, putRule, deleteRule, listTargetsByRule, putTargets, removeTargets
24
+ apiLambdaFunctionArn, eventBusName = "default", jobNamePrefix = "claire-aws-job-") {
130
25
  super(logger, db);
131
26
  this.logger = logger;
132
27
  this.db = db;
133
- this.redisClient = redisClient;
134
- this.uniqueIdKey = uniqueIdKey;
28
+ this.uniqueJobIdFactory = uniqueJobIdFactory;
135
29
  this.apiLambdaFunctionArn = apiLambdaFunctionArn;
136
- this.stepFunctionName = stepFunctionName;
137
- this.iamRoleArn = iamRoleArn;
138
30
  this.eventBusName = eventBusName;
139
31
  this.jobNamePrefix = jobNamePrefix;
140
- this.oneMinuteRule = oneMinuteRule;
141
- }
142
- async handleInterval(interval) {
143
- this.logger.debug(`Handle interval`, interval, typeof interval);
144
- const allJobs = await this.getAvailableJobInfo();
145
- const timedJobs = allJobs.filter((job) => job.interval && interval % job.interval === 0);
146
- await Promise.all(timedJobs.map((job) => this.executeJob({ ...job, id: job.jobName })));
147
32
  }
148
33
  async handleCron(jobInfo) {
149
34
  this.logger.debug(`Handle cron`, jobInfo);
@@ -168,7 +53,6 @@ let AwsJobScheduler = class AwsJobScheduler extends AbstractJobScheduler {
168
53
  return false;
169
54
  }
170
55
  async getAllScheduledJobs() {
171
- const availableJobs = await this.getAvailableJobInfo();
172
56
  const allRules = await this.eventbridge
173
57
  .listRules({
174
58
  EventBusName: this.eventBusName,
@@ -191,15 +75,12 @@ let AwsJobScheduler = class AwsJobScheduler extends AbstractJobScheduler {
191
75
  return jobInfo;
192
76
  }));
193
77
  //-- concat with interval jobs because we don't register them
194
- return allJobs
195
- .filter((job) => !!job)
196
- .concat(availableJobs.filter((j) => j.interval).map((j) => ({ ...j, id: j.jobName })));
78
+ return allJobs.filter((job) => !!job);
197
79
  }
198
80
  async scheduleJob(jobInfo) {
199
81
  this.logger.debug("Scheduling job: ", jobInfo);
200
82
  if (jobInfo.cron || jobInfo.at) {
201
- const uniqueId = await this.redisClient.incr(this.uniqueIdKey);
202
- const jobId = `${this.jobNamePrefix}${uniqueId}`;
83
+ const jobId = `${this.jobNamePrefix}${this.uniqueJobIdFactory()}`;
203
84
  //-- generate pattern from cron (add * at the end for year) / at timestamp
204
85
  const cronExpression = jobInfo.cron ? `${jobInfo.cron} *` : this.generateCronFromTimestamp(jobInfo.at);
205
86
  this.logger.debug("Cron expression", cronExpression);
@@ -234,18 +115,11 @@ let AwsJobScheduler = class AwsJobScheduler extends AbstractJobScheduler {
234
115
  .promise();
235
116
  return jobId;
236
117
  }
237
- else if (jobInfo.interval) {
238
- //-- interval job does not need to persist, the step function will take care of it
239
- return jobInfo.jobName;
240
- }
241
118
  else {
242
119
  throw Errors.SYSTEM_ERROR(`Job does not have time config: ${jobInfo.jobName}`);
243
120
  }
244
121
  }
245
122
  async syncJobs() {
246
- //-- check and init step function: step function must trigger lambda every 5s
247
- this.logger.debug("Checking interval scheduler");
248
- await this.checkIntervalScheduler();
249
123
  //-- check jobs
250
124
  const scheduledJobs = await this.getAllScheduledJobs();
251
125
  const allJobs = await this.getAvailableJobInfo();
@@ -263,13 +137,12 @@ let AwsJobScheduler = class AwsJobScheduler extends AbstractJobScheduler {
263
137
  const scheduledCronJobs = scheduledJobs.filter((j) => j.cron);
264
138
  await Promise.all(scheduledCronJobs.map((j) => this.removeJob(j.id)));
265
139
  //-- reschedule cron & interval jobs because we might have updated the cron expression / interval value
266
- const cronJobs = allJobs.filter((job) => job.cron || job.interval);
140
+ const cronJobs = allJobs.filter((job) => job.cron);
267
141
  this.logger.debug("Scheduling cron & interval jobs");
268
142
  for (const job of cronJobs) {
269
143
  await this.scheduleJob({
270
144
  jobName: job.jobName,
271
145
  cron: job.cron,
272
- interval: job.interval,
273
146
  });
274
147
  }
275
148
  //-- keep "at" jobs as is
@@ -289,125 +162,10 @@ let AwsJobScheduler = class AwsJobScheduler extends AbstractJobScheduler {
289
162
  })
290
163
  .promise();
291
164
  }
292
- async checkIntervalScheduler() {
293
- //-- check and create the step function
294
- const allJobs = await this.getAvailableJobInfo();
295
- const intervalJobs = allJobs.filter((j) => j.interval);
296
- const allIntervals = intervalJobs.map((j) => j.interval);
297
- const [interval, oneMinuteFunctionDefinition] = oneMinuteFunctionFactory(this.apiLambdaFunctionArn, allIntervals);
298
- this.logger.debug("Listing all state machines");
299
- const allMachines = await this.stepfunctions.listStateMachines({}).promise();
300
- let oldStateMachineArn = allMachines.stateMachines.find((s) => s.name.includes(this.stepFunctionName))?.stateMachineArn;
301
- let newStateMachineArn = oldStateMachineArn;
302
- if (oldStateMachineArn) {
303
- //-- check definition, if different then clear newStateMachineArn to create new one
304
- const describeResult = await this.stepfunctions
305
- .describeStateMachine({
306
- stateMachineArn: oldStateMachineArn,
307
- })
308
- .promise();
309
- //-- check the interval
310
- if (!describeResult.definition.includes(getWaitExpression(interval))) {
311
- this.logger.debug("Step function definition changed, create new state machine");
312
- newStateMachineArn = "";
313
- }
314
- }
315
- const awsStateMachineName = `${this.stepFunctionName}-${interval}`;
316
- if (!newStateMachineArn) {
317
- this.logger.debug(`Create new step function with interval ${interval} seconds`);
318
- const result = await this.stepfunctions
319
- .createStateMachine({
320
- definition: oneMinuteFunctionDefinition,
321
- name: awsStateMachineName,
322
- roleArn: this.iamRoleArn,
323
- type: "EXPRESS",
324
- })
325
- .promise();
326
- newStateMachineArn = result.stateMachineArn;
327
- }
328
- this.logger.debug("Step function ARNs old / new", oldStateMachineArn, newStateMachineArn);
329
- //-- check and create the one-minute-rule that trigger step function
330
- this.logger.debug("Getting one minute rule");
331
- const matchedRules = await this.eventbridge
332
- .listRules({
333
- EventBusName: this.eventBusName,
334
- NamePrefix: this.oneMinuteRule,
335
- })
336
- .promise();
337
- const oneMinuteRule = matchedRules.Rules?.find((r) => r.Name == this.oneMinuteRule);
338
- if (!oneMinuteRule) {
339
- this.logger.debug("Create new one minute rule");
340
- //-- one minute rule does not exist, create new
341
- await this.eventbridge
342
- .putRule({
343
- EventBusName: this.eventBusName,
344
- Name: this.oneMinuteRule,
345
- Description: "One minute trigger function for step function",
346
- ScheduleExpression: "rate(1 minute)",
347
- State: "ENABLED",
348
- })
349
- .promise();
350
- }
351
- this.logger.debug("Adding step function state machine as target");
352
- if (newStateMachineArn !== oldStateMachineArn) {
353
- //-- if there is old target then remove it
354
- if (oldStateMachineArn) {
355
- this.logger.debug("Removing old target", oldStateMachineArn);
356
- //-- remove old target
357
- await this.eventbridge
358
- .removeTargets({
359
- EventBusName: this.eventBusName,
360
- Rule: this.oneMinuteRule,
361
- Ids: [this.stepFunctionName],
362
- })
363
- .promise();
364
- this.logger.debug("Removing old state machine function");
365
- await this.stepfunctions
366
- .deleteStateMachine({
367
- stateMachineArn: oldStateMachineArn,
368
- })
369
- .promise();
370
- }
371
- //-- add the step function as call target
372
- this.logger.debug("Adding new target", newStateMachineArn);
373
- await this.eventbridge
374
- .putTargets({
375
- Rule: this.oneMinuteRule,
376
- Targets: [
377
- {
378
- Arn: newStateMachineArn,
379
- Id: this.stepFunctionName,
380
- RoleArn: this.iamRoleArn,
381
- },
382
- ],
383
- })
384
- .promise();
385
- }
386
- //-- if we don't have any interval job then disable the one minuter
387
- if (!intervalJobs.length && oneMinuteRule?.State) {
388
- this.logger.info("No interval job found, disable one minute rule");
389
- await this.eventbridge
390
- .disableRule({
391
- EventBusName: this.eventBusName,
392
- Name: this.oneMinuteRule,
393
- })
394
- .promise();
395
- }
396
- else {
397
- this.logger.info("Interval job found, enable one minute rule");
398
- await this.eventbridge
399
- .enableRule({
400
- EventBusName: this.eventBusName,
401
- Name: this.oneMinuteRule,
402
- })
403
- .promise();
404
- }
405
- }
406
165
  };
407
166
  AwsJobScheduler = __decorate([
408
167
  LogContext(),
409
168
  __metadata("design:paramtypes", [AbstractLogger,
410
- AbstractDbAdapter,
411
- Redis, String, String, String, String, Object, Object, Object])
169
+ AbstractDbAdapter, Function, String, Object, Object])
412
170
  ], AwsJobScheduler);
413
171
  export { AwsJobScheduler };
@@ -29,7 +29,7 @@ export declare class LocalJobScheduler extends AbstractJobScheduler implements I
29
29
  /**
30
30
  * The time to lock active scheduler
31
31
  */
32
- protected readonly keyRetentionDurationSecond: number;
32
+ protected readonly keyRetentionDurationSeconds: number;
33
33
  protected intervals: any[];
34
34
  private mutexHoldInterval?;
35
35
  private isActive;
@@ -55,7 +55,7 @@ export declare class LocalJobScheduler extends AbstractJobScheduler implements I
55
55
  /**
56
56
  * The time to lock active scheduler
57
57
  */
58
- keyRetentionDurationSecond?: number);
58
+ keyRetentionDurationSeconds?: number);
59
59
  private sendJob;
60
60
  private processMessage;
61
61
  private extendMutexKey;
@@ -32,7 +32,7 @@ let LocalJobScheduler = class LocalJobScheduler extends AbstractJobScheduler {
32
32
  holdMutexKey;
33
33
  uniqueIdKey;
34
34
  multiClientChannel;
35
- keyRetentionDurationSecond;
35
+ keyRetentionDurationSeconds;
36
36
  intervals = [];
37
37
  mutexHoldInterval;
38
38
  isActive = false;
@@ -58,7 +58,7 @@ let LocalJobScheduler = class LocalJobScheduler extends AbstractJobScheduler {
58
58
  /**
59
59
  * The time to lock active scheduler
60
60
  */
61
- keyRetentionDurationSecond = 30) {
61
+ keyRetentionDurationSeconds = 30) {
62
62
  super(logger, db);
63
63
  this.logger = logger;
64
64
  this.db = db;
@@ -69,7 +69,7 @@ let LocalJobScheduler = class LocalJobScheduler extends AbstractJobScheduler {
69
69
  this.holdMutexKey = holdMutexKey;
70
70
  this.uniqueIdKey = uniqueIdKey;
71
71
  this.multiClientChannel = multiClientChannel;
72
- this.keyRetentionDurationSecond = keyRetentionDurationSecond;
72
+ this.keyRetentionDurationSeconds = keyRetentionDurationSeconds;
73
73
  }
74
74
  sendJob(type, messageId, data) {
75
75
  this.subscribeClient.publish(this.multiClientChannel, JSON.stringify({ type, messageId, data }));
@@ -116,7 +116,7 @@ let LocalJobScheduler = class LocalJobScheduler extends AbstractJobScheduler {
116
116
  if (!this.redisClient) {
117
117
  return;
118
118
  }
119
- await this.redisClient.setex(this.holdMutexKey, this.keyRetentionDurationSecond, 1);
119
+ await this.redisClient.setex(this.holdMutexKey, this.keyRetentionDurationSeconds, 1);
120
120
  this.logger.debug("Scheduler extends mutex key");
121
121
  }
122
122
  async afterJob({ at, ...job }, tx) {
@@ -139,15 +139,15 @@ let LocalJobScheduler = class LocalJobScheduler extends AbstractJobScheduler {
139
139
  //-- try to claim active scheduler
140
140
  const locker = new Redlock([this.redisClient]);
141
141
  try {
142
- const lock = await locker.acquire([this.lockMutexKey], this.keyRetentionDurationSecond);
142
+ const lock = await locker.acquire([this.lockMutexKey], this.keyRetentionDurationSeconds * 1000);
143
143
  this.isActive = true;
144
144
  await this.extendMutexKey();
145
145
  await lock.release();
146
- this.logger.debug("Being active scheduler");
146
+ this.logger.debug("Became active scheduler");
147
147
  //-- actively hold the mutex key
148
148
  this.mutexHoldInterval = setInterval(() => {
149
149
  this.extendMutexKey();
150
- }, Math.trunc((this.keyRetentionDurationSecond * 1000) / 2) + 1);
150
+ }, Math.trunc((this.keyRetentionDurationSeconds * 1000) / 2) + 1);
151
151
  }
152
152
  catch (err) {
153
153
  this.logger.info("Failed to lock mutex key, ignore", err);
@@ -175,7 +175,7 @@ let LocalJobScheduler = class LocalJobScheduler extends AbstractJobScheduler {
175
175
  //-- schedule all cron & interval jobs
176
176
  const allJobs = await this.getAvailableJobInfo();
177
177
  for (const job of allJobs) {
178
- if (job.cron || job.interval) {
178
+ if (job.cron) {
179
179
  await this.scheduleJob(job);
180
180
  }
181
181
  }
@@ -214,16 +214,6 @@ let LocalJobScheduler = class LocalJobScheduler extends AbstractJobScheduler {
214
214
  this.jobHolder[id] = { jobCanceler: () => clearTimeout(timeout), jobInfo: { ...jobInfo, id } };
215
215
  return id;
216
216
  }
217
- else if (jobInfo.interval) {
218
- const id = jobInfo.jobName;
219
- //-- set interval and does not need to persist
220
- const scheduledJob = { ...jobInfo, id };
221
- const interval = setInterval(() => {
222
- this.executeJob(scheduledJob).catch((err) => this.logger.error(`Error execute job ${scheduledJob.jobName} with id: ${scheduledJob.id}`, err));
223
- }, jobInfo.interval);
224
- this.jobHolder[id] = { jobCanceler: () => clearInterval(interval), jobInfo: { ...jobInfo, id } };
225
- return id;
226
- }
227
217
  else if (jobInfo.cron) {
228
218
  const id = jobInfo.jobName;
229
219
  //-- set cron and does not need to persist
@@ -1,5 +1,3 @@
1
1
  import { AbstractJobController } from "./AbstractJobController";
2
- import { JobInterval } from "./interfaces";
3
- export declare const IntervalJob: (jobName: string, interval: JobInterval) => <T extends AbstractJobController>(prototype: T, propertyKey: keyof T) => void;
4
2
  export declare const CronJob: (jobName: string, cron: string) => <T extends AbstractJobController>(prototype: T, propertyKey: keyof T) => void;
5
3
  export declare const CustomJob: (jobName: string) => <T extends AbstractJobController>(prototype: T, propertyKey: keyof T) => void;
@@ -1,23 +1,4 @@
1
1
  import { Errors, initObjectMetadata } from "@clairejs/core";
2
- export const IntervalJob = (
3
- /**
4
- * Unique name of job
5
- */
6
- jobName,
7
- /**
8
- * Interval duration in second
9
- */
10
- interval) => (prototype, propertyKey) => {
11
- const metadata = initObjectMetadata(prototype);
12
- if (!metadata.jobs) {
13
- metadata.jobs = [];
14
- }
15
- metadata.jobs.push({
16
- jobName,
17
- interval,
18
- handlerName: propertyKey,
19
- });
20
- };
21
2
  export const CronJob = (
22
3
  /**
23
4
  * Unique name of job
@@ -1,22 +1,10 @@
1
1
  import { ObjectMetadata } from "@clairejs/core";
2
- export declare const INTERVAL_REQUEST_METHOD = "interval";
3
2
  export declare const CRON_REQUEST_METHOD = "cron";
4
- export declare enum JobInterval {
5
- EVERY_5S = 5,
6
- EVERY_10S = 10,
7
- EVERY_15S = 15,
8
- EVERY_20S = 20,
9
- EVERY_30S = 30
10
- }
11
3
  export interface JobInfoMetadata {
12
4
  /**
13
5
  * Unique name of job
14
6
  */
15
7
  jobName: string;
16
- /**
17
- * Interval in seconds
18
- */
19
- interval?: JobInterval;
20
8
  /**
21
9
  * Run with cron expression, does not support seconds precision
22
10
  */
@@ -44,7 +32,6 @@ export interface JobInfo {
44
32
  jobName: string;
45
33
  params?: any;
46
34
  at?: number;
47
- interval?: JobInterval;
48
35
  cron?: string;
49
36
  }
50
37
  export interface ScheduledJob extends JobInfo {
@@ -1,10 +1 @@
1
- export const INTERVAL_REQUEST_METHOD = "interval";
2
1
  export const CRON_REQUEST_METHOD = "cron";
3
- export var JobInterval;
4
- (function (JobInterval) {
5
- JobInterval[JobInterval["EVERY_5S"] = 5] = "EVERY_5S";
6
- JobInterval[JobInterval["EVERY_10S"] = 10] = "EVERY_10S";
7
- JobInterval[JobInterval["EVERY_15S"] = 15] = "EVERY_15S";
8
- JobInterval[JobInterval["EVERY_20S"] = 20] = "EVERY_20S";
9
- JobInterval[JobInterval["EVERY_30S"] = 30] = "EVERY_30S";
10
- })(JobInterval || (JobInterval = {}));
@@ -35,10 +35,10 @@ let ClaireServer = class ClaireServer extends ClaireApp {
35
35
  }
36
36
  //-- save mounted endpoint info in server store to prevent circular dependency when resolving http request handler in controller
37
37
  for (const endpoint of mountedEndpointInfo) {
38
- this.logger.info(`Mounting: ${endpoint.method}:${endpoint.mount}`);
38
+ this.logger.debug(`Mounting: ${endpoint.method}:${endpoint.mount}`);
39
39
  }
40
40
  getGlobalStore().mountedEndpointInfo = mountedEndpointInfo;
41
- this.logger.debug("Claire server initing");
41
+ this.logger.info("Claire server initing");
42
42
  //-- handle exceptions
43
43
  this.logger.debug(`Setting up exception handlers`);
44
44
  process.on("SIGTERM", () => {
@@ -1,7 +1,7 @@
1
1
  import { getServiceProvider, HttpMethod, SocketMethod, Errors } from "@clairejs/core";
2
2
  import { AbstractHttpRequestHandler } from "../http/controller/AbstractHttpRequestHandler";
3
3
  import { AwsJobScheduler } from "../job/AwsJobScheduler";
4
- import { CRON_REQUEST_METHOD, INTERVAL_REQUEST_METHOD } from "../job/interfaces";
4
+ import { CRON_REQUEST_METHOD } from "../job/interfaces";
5
5
  import { AbstractServerSocketManager } from "../socket/AbstractServerSocketManager";
6
6
  const convertCorsToHeaders = (origin, cors) => {
7
7
  const headers = {};
@@ -99,10 +99,6 @@ export class LambdaWrapper {
99
99
  if (requestOptions.method === HttpMethod.OPTIONS) {
100
100
  return toApiGatewayFormat({ code: 200, headers: corsHeaders, cookies: {} });
101
101
  }
102
- if (requestOptions.method === INTERVAL_REQUEST_METHOD) {
103
- await this.jobScheduler?.handleInterval(requestOptions.body);
104
- return toApiGatewayFormat({ code: 200, headers: corsHeaders, cookies: {} });
105
- }
106
102
  if (requestOptions.method === CRON_REQUEST_METHOD) {
107
103
  await this.jobScheduler?.handleCron(requestOptions.body);
108
104
  return toApiGatewayFormat({ code: 200, headers: corsHeaders, cookies: {} });
@@ -1,5 +1,5 @@
1
1
  import { SocketMethod } from "@clairejs/core";
2
- import { CRON_REQUEST_METHOD, INTERVAL_REQUEST_METHOD } from "../job/interfaces";
2
+ import { CRON_REQUEST_METHOD } from "../job/interfaces";
3
3
  const parseCookie = (cookieArray) => {
4
4
  let result = {};
5
5
  for (const cookie of cookieArray) {
@@ -21,14 +21,6 @@ export const lambdaRequestMapper = (event) => {
21
21
  body: method === SocketMethod.CONNECT ? { queries: event.queryStringParameters } : body,
22
22
  };
23
23
  }
24
- if (event.requestContext.intervalScheduler) {
25
- //-- interval scheduler
26
- return {
27
- method: INTERVAL_REQUEST_METHOD,
28
- rawPath: "",
29
- body: event.requestContext.intervalScheduler.time,
30
- };
31
- }
32
24
  if (event.requestContext.cronScheduler) {
33
25
  //-- cron scheduler
34
26
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clairejs/server",
3
- "version": "3.20.1",
3
+ "version": "3.21.0",
4
4
  "description": "Claire server NodeJs framework written in Typescript.",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
@@ -34,7 +34,7 @@
34
34
  "ws": "^7.5.5"
35
35
  },
36
36
  "peerDependencies": {
37
- "@clairejs/core": "^3.8.4",
37
+ "@clairejs/core": "^3.8.7",
38
38
  "@clairejs/orm": "^3.16.0"
39
39
  },
40
40
  "devDependencies": {