badmfck-api-server 4.0.80 → 4.0.82

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.
@@ -97,7 +97,7 @@ async function Initializer(services) {
97
97
  }
98
98
  exports.Initializer = Initializer;
99
99
  class APIService extends BaseService_1.BaseService {
100
- version = "4.0.79";
100
+ version = "4.0.81";
101
101
  options;
102
102
  monitor = null;
103
103
  started = new Date();
@@ -11,16 +11,18 @@ export interface ITimeframeTask<T = any> {
11
11
  executed: number;
12
12
  retries?: number;
13
13
  maxRetries?: number;
14
+ processing?: boolean;
14
15
  }
15
16
  export declare class TimeframeService extends BaseService {
16
17
  TICK_INTERVAL_MS: number;
17
18
  RETRY_DELAY_MS: number;
18
19
  GRACE_WINDOW_MS: number;
19
20
  tasks: ITimeframeTask<any>[];
20
- intervalId: any;
21
+ private intervalId;
21
22
  static wait(ms: number): Promise<void>;
22
23
  constructor();
23
24
  init(): Promise<void>;
24
- finishService(): Promise<void>;
25
25
  loop(): Promise<void>;
26
+ private runTask;
27
+ finishService(): Promise<void>;
26
28
  }
@@ -43,55 +43,78 @@ class TimeframeService extends BaseService_1.BaseService {
43
43
  }
44
44
  async init() {
45
45
  exports.REQ_TIMEFRAME_TASK_ADD.listener = async (req) => {
46
- (0, LogService_1.logInfo)("Add tack " + req.name);
47
- this.tasks.push(req);
46
+ (0, LogService_1.logInfo)("Add task " + req.name);
47
+ this.tasks.push({
48
+ ...req,
49
+ executed: 0,
50
+ retries: 0,
51
+ processing: false
52
+ });
48
53
  };
49
54
  this.intervalId = setInterval(() => {
50
- this.loop();
55
+ this.loop().catch(console.error);
51
56
  }, this.TICK_INTERVAL_MS);
52
57
  }
53
- async finishService() {
54
- clearInterval(this.intervalId);
55
- }
56
58
  async loop() {
57
59
  const now = Date.now();
58
60
  for (let i = 0; i < this.tasks.length; i++) {
59
61
  const task = this.tasks[i];
60
62
  if (!task)
61
63
  continue;
62
- if (now >= task.start && (!task.executed || task.executed < task.start)) {
64
+ if (task.repeat && !task.processing && now > (task.start + this.GRACE_WINDOW_MS)) {
65
+ const diff = now - task.start;
66
+ const missedIntervals = Math.ceil(diff / task.repeat);
67
+ task.start += missedIntervals * task.repeat;
68
+ (0, LogService_1.logInfo)(`Task ${task.name} skipped and rescheduled to ${new Date(task.start).toLocaleTimeString()}`);
69
+ continue;
70
+ }
71
+ const isReady = now >= task.start;
72
+ const isNotExecutedYet = !task.executed || task.executed < task.start;
73
+ if (isReady && isNotExecutedYet && !task.processing) {
63
74
  if (now - task.start <= this.GRACE_WINDOW_MS) {
64
- try {
65
- (0, LogService_1.logInfo)("Execute task ", task.name);
66
- if (task.callback.length > 0 && task.params)
67
- task.callback(task.params);
68
- else
69
- task.callback();
70
- task.executed = Date.now();
71
- task.retries = 0;
72
- (0, LogService_1.logInfo)("Executed task ", task.name);
73
- if (task.repeat) {
74
- task.start += task.repeat;
75
- }
76
- else {
77
- this.tasks.splice(i, 1);
78
- i--;
79
- }
80
- }
81
- catch (e) {
82
- task.retries = (task.retries || 0) + 1;
83
- if (task.retries > (task.maxRetries ?? 0)) {
84
- console.warn(`Task ${task.name} failed too many times`);
85
- this.tasks.splice(i, 1);
86
- i--;
87
- }
88
- else {
89
- task.start = now + 10_000;
90
- }
91
- }
75
+ this.runTask(task);
76
+ }
77
+ else if (!task.repeat) {
78
+ (0, LogService_1.logInfo)(`One-off task ${task.name} missed grace window. Dropping.`);
79
+ task.executed = now;
80
+ this.tasks = this.tasks.filter(t => t !== task);
92
81
  }
93
82
  }
94
83
  }
95
84
  }
85
+ async runTask(task) {
86
+ task.processing = true;
87
+ try {
88
+ (0, LogService_1.logInfo)("Execute task ", task.name);
89
+ await task.callback(task.params);
90
+ task.executed = Date.now();
91
+ task.retries = 0;
92
+ (0, LogService_1.logInfo)("Executed task ", task.name);
93
+ if (task.repeat) {
94
+ task.start += task.repeat;
95
+ }
96
+ else {
97
+ this.tasks = this.tasks.filter(t => t !== task);
98
+ }
99
+ exports.S_TIMEFRAME_TASK_EXECUTED.invoke(task);
100
+ }
101
+ catch (e) {
102
+ console.error(`Task ${task.name} error:`, e);
103
+ task.retries = (task.retries || 0) + 1;
104
+ if (task.retries > (task.maxRetries ?? 0)) {
105
+ console.warn(`Task ${task.name} failed too many times. Dropping.`);
106
+ this.tasks = this.tasks.filter(t => t !== task);
107
+ }
108
+ else {
109
+ task.start = Date.now() + this.RETRY_DELAY_MS;
110
+ }
111
+ }
112
+ finally {
113
+ task.processing = false;
114
+ }
115
+ }
116
+ async finishService() {
117
+ clearInterval(this.intervalId);
118
+ }
96
119
  }
97
120
  exports.TimeframeService = TimeframeService;
@@ -157,6 +157,8 @@ class Validator {
157
157
  let num = parseInt(object[i]);
158
158
  if (object[i].includes("."))
159
159
  num = parseFloat(object[i]);
160
+ if (isNaN(num))
161
+ num = structureOptions.default !== undefined ? structureOptions.default : NaN;
160
162
  if (isNaN(num))
161
163
  errors.push("wrong value for field '" + parentPath + i + "', expected number got " + object[i]);
162
164
  else
@@ -209,6 +211,10 @@ class Validator {
209
211
  structureOptions.values = structure['$__' + i + "_values"];
210
212
  if (Array.isArray(structureOptions.values) && structureOptions.values.length) {
211
213
  if (!structureOptions.values.includes(object[i])) {
214
+ if (structureOptions.default && structureOptions.values.includes(structureOptions.default)) {
215
+ object[i] = structureOptions.default;
216
+ continue;
217
+ }
212
218
  let caseValue = null;
213
219
  for (let i of structureOptions.values) {
214
220
  if (i === null || i === undefined)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "badmfck-api-server",
3
- "version": "4.0.80",
3
+ "version": "4.0.82",
4
4
  "description": "Simple API http server based on express",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",