@balena/pinejs 16.2.0-build-joshbwlng-tasks-cd1aff5f4bbfacaad189b013578d5cbee51c3932-1 → 16.2.0-build-joshbwlng-tasks-a83c83b4c78803915d0cb6297cc8cc1862622d08-1

Sign up to get free protection for your applications and to get access to all the features.
package/.husky/pre-commit CHANGED
@@ -1,4 +1,2 @@
1
- #!/usr/bin/env sh
2
- . "$(dirname -- "$0")/_/husky.sh"
3
1
 
4
2
  npx --no lint-staged
@@ -1,14 +1,6 @@
1
1
  - commits:
2
- - subject: Organize code
3
- hash: cd1aff5f4bbfacaad189b013578d5cbee51c3932
4
- body: ""
5
- footer:
6
- Change-type: patch
7
- change-type: patch
8
- author: Josh Bowling
9
- nested: []
10
2
  - subject: Add async tasks
11
- hash: 2b1a04b883e932516582ba8c9f0fc4d5913d5335
3
+ hash: a83c83b4c78803915d0cb6297cc8cc1862622d08
12
4
  body: ""
13
5
  footer:
14
6
  Change-type: minor
@@ -17,7 +9,33 @@
17
9
  nested: []
18
10
  version: 16.2.0
19
11
  title: ""
20
- date: 2024-04-10T23:12:22.210Z
12
+ date: 2024-04-15T01:28:02.918Z
13
+ - commits:
14
+ - subject: Update dependency husky to v9
15
+ hash: 715d2dd993591d449bca7ece48f069ed6994c8c7
16
+ body: |
17
+ Update husky from 8.0.3 to 9.0.11
18
+ footer:
19
+ Change-type: patch
20
+ change-type: patch
21
+ author: Self-hosted Renovate Bot
22
+ nested: []
23
+ version: 16.1.2
24
+ title: ""
25
+ date: 2024-04-14T04:09:27.077Z
26
+ - commits:
27
+ - subject: Update dependency @balena/lint to v8
28
+ hash: 02ba2563aa4ac82ad90accc30534f744c00a0c16
29
+ body: |
30
+ Update @balena/lint from 7.3.0 to 8.0.0
31
+ footer:
32
+ Change-type: patch
33
+ change-type: patch
34
+ author: Self-hosted Renovate Bot
35
+ nested: []
36
+ version: 16.1.1
37
+ title: ""
38
+ date: 2024-04-11T22:45:27.398Z
21
39
  - commits:
22
40
  - subject: Add support for prettifying index constraint errors with their
23
41
  description
package/CHANGELOG.md CHANGED
@@ -5,11 +5,20 @@ automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
5
5
  This project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
7
  # v16.2.0
8
- ## (2024-04-10)
8
+ ## (2024-04-15)
9
9
 
10
- * Organize code [Josh Bowling]
11
10
  * Add async tasks [Josh Bowling]
12
11
 
12
+ # v16.1.2
13
+ ## (2024-04-14)
14
+
15
+ * Update dependency husky to v9 [Self-hosted Renovate Bot]
16
+
17
+ # v16.1.1
18
+ ## (2024-04-11)
19
+
20
+ * Update dependency @balena/lint to v8 [Self-hosted Renovate Bot]
21
+
13
22
  # v16.1.0
14
23
  ## (2024-04-02)
15
24
 
@@ -8,9 +8,9 @@ export declare class Worker {
8
8
  private executing;
9
9
  constructor(client: PinejsClient);
10
10
  private canExecute;
11
- private poll;
12
- start(): void;
13
11
  private execute;
12
+ private finalize;
14
13
  private getNextAttemptTime;
15
- private update;
14
+ private poll;
15
+ start(): void;
16
16
  }
@@ -52,73 +52,18 @@ class Worker {
52
52
  canExecute() {
53
53
  return (this.executing < this.concurrency && Object.keys(this.handlers).length > 0);
54
54
  }
55
- poll() {
56
- let executed = false;
57
- const names = Object.keys(this.handlers);
58
- const binds = names.map((_, index) => `$${index + 1}`).join(', ');
59
- module_1.sbvrUtils.db
60
- .transaction(async (tx) => {
61
- if (!this.canExecute()) {
62
- return;
63
- }
64
- const result = await tx.executeSql(`SELECT ${selectColumns}
65
- FROM task AS t
66
- WHERE
67
- t."is executed by-handler" IN (${binds}) AND
68
- t."status" = 'pending' AND
69
- t."attempt count" <= t."attempt limit" AND
70
- (
71
- t."is scheduled to execute on-time" IS NULL OR
72
- t."is scheduled to execute on-time" <= CURRENT_TIMESTAMP + INTERVAL '${Math.ceil(this.interval / 1000)} second'
73
- )
74
- ORDER BY
75
- t."is scheduled to execute on-time" ASC,
76
- t."priority" DESC,
77
- t."id" ASC
78
- LIMIT ${Math.max(this.concurrency - this.executing, 0)}
79
- FOR UPDATE SKIP LOCKED`, names);
80
- if (result.rows.length === 0) {
81
- return;
82
- }
83
- await Promise.all(result.rows.map(async (row) => {
84
- await this.execute(tx, row);
85
- }));
86
- executed = true;
87
- })
88
- .catch((err) => {
89
- console.error('Failed polling for tasks:', err);
90
- })
91
- .finally(() => {
92
- setTimeout(() => this.poll(), executed ? 0 : this.interval);
93
- });
94
- }
95
- start() {
96
- module_1.sbvrUtils.db.on?.('notification', async (msg) => {
97
- if (this.canExecute()) {
98
- await module_1.sbvrUtils.db.transaction(async (tx) => {
99
- const result = await tx.executeSql(`SELECT ${selectColumns} FROM task AS t WHERE id = $1 FOR UPDATE SKIP LOCKED`, [msg.payload]);
100
- if (result.rows.length > 0) {
101
- await this.execute(tx, result.rows[0]);
102
- }
103
- });
104
- }
105
- }, {
106
- channel: common_1.channel,
107
- });
108
- this.poll();
109
- }
110
55
  async execute(tx, task) {
111
56
  this.executing++;
112
57
  try {
113
58
  const handler = this.handlers[task.is_executed_by__handler];
114
59
  const startedOnTime = new Date();
115
60
  if (handler == null) {
116
- await this.update(tx, task, startedOnTime, 'failed', 'Matching task handler not found');
61
+ await this.finalize(tx, task, startedOnTime, 'failed', 'Matching task handler not found');
117
62
  return;
118
63
  }
119
64
  if (handler.validate != null &&
120
65
  !handler.validate(task.is_executed_with__parameter_set)) {
121
- await this.update(tx, task, startedOnTime, 'failed', `Invalid parameter set: ${common_1.ajv.errorsText(handler.validate.errors)}`);
66
+ await this.finalize(tx, task, startedOnTime, 'failed', `Invalid parameter set: ${common_1.ajv.errorsText(handler.validate.errors)}`);
122
67
  return;
123
68
  }
124
69
  const result = await handler.fn({
@@ -130,7 +75,7 @@ class Worker {
130
75
  params: task.is_executed_with__parameter_set ?? {},
131
76
  tx,
132
77
  });
133
- await this.update(tx, task, startedOnTime, result.status, result.error);
78
+ await this.finalize(tx, task, startedOnTime, result.status, result.error);
134
79
  }
135
80
  catch (err) {
136
81
  console.error('Task execution failed:', err);
@@ -140,11 +85,7 @@ class Worker {
140
85
  this.executing--;
141
86
  }
142
87
  }
143
- getNextAttemptTime(attempt) {
144
- const delay = Math.ceil(Math.exp(Math.min(10, attempt))) * 1000;
145
- return new Date(Date.now() + delay);
146
- }
147
- async update(tx, task, startedOnTime, status, errorMessage) {
88
+ async finalize(tx, task, startedOnTime, status, errorMessage) {
148
89
  const attemptCount = task.attempt_count + 1;
149
90
  const body = {
150
91
  started_on__time: startedOnTime,
@@ -186,6 +127,65 @@ class Worker {
186
127
  });
187
128
  }
188
129
  }
130
+ getNextAttemptTime(attempt) {
131
+ const delay = Math.ceil(Math.exp(Math.min(10, attempt))) * 1000;
132
+ return new Date(Date.now() + delay);
133
+ }
134
+ poll() {
135
+ let executed = false;
136
+ const handlerNames = Object.keys(this.handlers);
137
+ const binds = handlerNames.map((_, index) => `$${index + 1}`).join(', ');
138
+ module_1.sbvrUtils.db
139
+ .transaction(async (tx) => {
140
+ if (!this.canExecute()) {
141
+ return;
142
+ }
143
+ const result = await tx.executeSql(`SELECT ${selectColumns}
144
+ FROM task AS t
145
+ WHERE
146
+ t."is executed by-handler" IN (${binds}) AND
147
+ t."status" = 'pending' AND
148
+ t."attempt count" <= t."attempt limit" AND
149
+ (
150
+ t."is scheduled to execute on-time" IS NULL OR
151
+ t."is scheduled to execute on-time" <= CURRENT_TIMESTAMP + INTERVAL '${Math.ceil(this.interval / 1000)} second'
152
+ )
153
+ ORDER BY
154
+ t."is scheduled to execute on-time" ASC,
155
+ t."priority" DESC,
156
+ t."id" ASC
157
+ LIMIT ${Math.max(this.concurrency - this.executing, 0)}
158
+ FOR UPDATE SKIP LOCKED`, handlerNames);
159
+ if (result.rows.length === 0) {
160
+ return;
161
+ }
162
+ await Promise.all(result.rows.map(async (row) => {
163
+ await this.execute(tx, row);
164
+ }));
165
+ executed = true;
166
+ })
167
+ .catch((err) => {
168
+ console.error('Failed polling for tasks:', err);
169
+ })
170
+ .finally(() => {
171
+ setTimeout(() => this.poll(), executed ? 0 : this.interval);
172
+ });
173
+ }
174
+ start() {
175
+ module_1.sbvrUtils.db.on?.('notification', async (msg) => {
176
+ if (this.canExecute()) {
177
+ await module_1.sbvrUtils.db.transaction(async (tx) => {
178
+ const result = await tx.executeSql(`SELECT ${selectColumns} FROM task AS t WHERE id = $1 FOR UPDATE SKIP LOCKED`, [msg.payload]);
179
+ if (result.rows.length > 0) {
180
+ await this.execute(tx, result.rows[0]);
181
+ }
182
+ });
183
+ }
184
+ }, {
185
+ channel: common_1.channel,
186
+ });
187
+ this.poll();
188
+ }
189
189
  }
190
190
  exports.Worker = Worker;
191
191
  //# sourceMappingURL=worker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/tasks/worker.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AACA,8CAAyD;AAEzD,qEAAuD;AACvD,uDAAsD;AACtD,kDAAkD;AAClD,qCAAwC;AAIxC,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC;IACpC,EAAE,EAAE,IAAI;IACR,wBAAwB,EAAE,yBAAyB;IACnD,gCAAgC,EAAE,iCAAiC;IACnE,mCAAmC,EAAE,oCAAoC;IACzE,eAAe,EAAE,eAAe;IAChC,eAAe,EAAE,eAAe;IAChC,QAAQ,EAAE,UAAU;IACpB,qBAAqB,EAAE,sBAAsB;CAC7C,CAAC;KACA,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,MAAM,GAAG,SAAS,KAAK,GAAG,CAAC;KACjD,IAAI,CAAC,IAAI,CAAC,CAAC;AAKb,MAAa,MAAM;IAOlB,YAAY,MAAoB;QANzB,aAAQ,GAAgC,EAAE,CAAC;QAI1C,cAAS,GAAG,CAAC,CAAC;QAGrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,WAAW,GAAG,WAAQ,CAAC,gBAAgB,CAAC;QAC7C,IAAI,CAAC,QAAQ,GAAG,WAAQ,CAAC,eAAe,CAAC;IAC1C,CAAC;IAEO,UAAU;QACjB,OAAO,CACN,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAC1E,CAAC;IACH,CAAC;IAEO,IAAI;QACX,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClE,kBAAS,CAAC,EAAE;aACV,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YACzB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;gBACxB,OAAO;YACR,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,UAAU,CACjC,UAAU,aAAa;;;sCAGU,KAAK;;;;;6EAKkC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;;;;;;YAMhG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;2BAC/B,EACtB,KAAK,CACL,CAAC;YACF,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAO;YACR,CAAC;YAGD,MAAM,OAAO,CAAC,GAAG,CAChB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;gBAC7B,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,GAAkB,CAAC,CAAC;YAC5C,CAAC,CAAC,CACF,CAAC;YACF,QAAQ,GAAG,IAAI,CAAC;QACjB,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAC;QACjD,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACb,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;IACL,CAAC;IAGM,KAAK;QACX,kBAAS,CAAC,EAAE,CAAC,EAAE,EAAE,CAChB,cAAc,EACd,KAAK,EAAE,GAAG,EAAE,EAAE;YACb,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;gBACvB,MAAM,kBAAS,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;oBAC3C,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,UAAU,CACjC,UAAU,aAAa,sDAAsD,EAC7E,CAAC,GAAG,CAAC,OAAO,CAAC,CACb,CAAC;oBACF,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC5B,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAgB,CAAC,CAAC;oBACvD,CAAC;gBACF,CAAC,CAAC,CAAC;YACJ,CAAC;QACF,CAAC,EACD;YACC,OAAO,EAAP,gBAAO;SACP,CACD,CAAC;QACF,IAAI,CAAC,IAAI,EAAE,CAAC;IACb,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,EAAS,EAAE,IAAiB;QACjD,IAAI,CAAC,SAAS,EAAE,CAAC;QACjB,IAAI,CAAC;YAEJ,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;YAC5D,MAAM,aAAa,GAAG,IAAI,IAAI,EAAE,CAAC;YACjC,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;gBACrB,MAAM,IAAI,CAAC,MAAM,CAChB,EAAE,EACF,IAAI,EACJ,aAAa,EACb,QAAQ,EACR,iCAAiC,CACjC,CAAC;gBACF,OAAO;YACR,CAAC;YAKD,IACC,OAAO,CAAC,QAAQ,IAAI,IAAI;gBACxB,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,+BAA+B,CAAC,EACtD,CAAC;gBACF,MAAM,IAAI,CAAC,MAAM,CAChB,EAAE,EACF,IAAI,EACJ,aAAa,EACb,QAAQ,EACR,0BAA0B,YAAG,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CACnE,CAAC;gBACF,OAAO;YACR,CAAC;YAGD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,CAAC;gBAC/B,GAAG,EAAE,IAAI,yBAAY,CAAC;oBACrB,WAAW,EAAE;wBACZ,EAAE;qBACF;iBACD,CAAC;gBACF,MAAM,EAAE,IAAI,CAAC,+BAA+B,IAAI,EAAE;gBAClD,EAAE;aACF,CAAC,CAAC;YAGH,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YAEd,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC;YAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;gBAAS,CAAC;YACV,IAAI,CAAC,SAAS,EAAE,CAAC;QAClB,CAAC;IACF,CAAC;IAEO,kBAAkB,CAAC,OAAe;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QAChE,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;IACrC,CAAC;IAEO,KAAK,CAAC,MAAM,CACnB,EAAS,EACT,IAAiB,EACjB,aAAmB,EACnB,MAAkB,EAClB,YAAqB;QAErB,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAc;YACvB,gBAAgB,EAAE,aAAa;YAC/B,cAAc,EAAE,IAAI,IAAI,EAAE;YAC1B,MAAM;YACN,aAAa,EAAE,YAAY;YAC3B,GAAG,CAAC,YAAY,IAAI,IAAI,IAAI,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC;SAC5D,CAAC;QAIF,IAAI,MAAM,KAAK,QAAQ,IAAI,YAAY,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YAC9D,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;YAGxB,IAAI,CAAC,gCAAgC;gBACpC,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;QACxC,CAAC;QAGD,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;YACvB,QAAQ,EAAE,MAAM;YAChB,WAAW,EAAE;gBACZ,EAAE;gBACF,GAAG,EAAE,WAAW,CAAC,IAAI;aACrB;YACD,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI;SACJ,CAAC,CAAC;QAIH,IACC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;YAC3C,IAAI,CAAC,kCAAkC,IAAI,IAAI,EAC9C,CAAC;YACF,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;gBACtB,QAAQ,EAAE,MAAM;gBAChB,WAAW,EAAE;oBACZ,EAAE;oBACF,GAAG,EAAE,WAAW,CAAC,IAAI;iBACrB;gBACD,IAAI,EAAE;oBACL,aAAa,EAAE,IAAI,CAAC,aAAa;oBACjC,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;oBAC/C,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;oBACrD,+BAA+B,EAAE,IAAI,CAAC,+BAA+B;oBACrE,kCAAkC,EACjC,IAAI,CAAC,kCAAkC;oBACxC,QAAQ,EAAE,IAAI,CAAC,QAAQ;iBACvB;aACD,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;CACD;AAtND,wBAsNC"}
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/tasks/worker.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AACA,8CAAyD;AAEzD,qEAAuD;AACvD,uDAAsD;AACtD,kDAAkD;AAClD,qCAAwC;AAIxC,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC;IACpC,EAAE,EAAE,IAAI;IACR,wBAAwB,EAAE,yBAAyB;IACnD,gCAAgC,EAAE,iCAAiC;IACnE,mCAAmC,EAAE,oCAAoC;IACzE,eAAe,EAAE,eAAe;IAChC,eAAe,EAAE,eAAe;IAChC,QAAQ,EAAE,UAAU;IACpB,qBAAqB,EAAE,sBAAsB;CAC7C,CAAC;KACA,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,MAAM,GAAG,SAAS,KAAK,GAAG,CAAC;KACjD,IAAI,CAAC,IAAI,CAAC,CAAC;AAKb,MAAa,MAAM;IAOlB,YAAY,MAAoB;QANzB,aAAQ,GAAgC,EAAE,CAAC;QAI1C,cAAS,GAAG,CAAC,CAAC;QAGrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,WAAW,GAAG,WAAQ,CAAC,gBAAgB,CAAC;QAC7C,IAAI,CAAC,QAAQ,GAAG,WAAQ,CAAC,eAAe,CAAC;IAC1C,CAAC;IAGO,UAAU;QACjB,OAAO,CACN,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAC1E,CAAC;IACH,CAAC;IAGO,KAAK,CAAC,OAAO,CAAC,EAAS,EAAE,IAAiB;QACjD,IAAI,CAAC,SAAS,EAAE,CAAC;QACjB,IAAI,CAAC;YAEJ,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;YAC5D,MAAM,aAAa,GAAG,IAAI,IAAI,EAAE,CAAC;YACjC,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;gBACrB,MAAM,IAAI,CAAC,QAAQ,CAClB,EAAE,EACF,IAAI,EACJ,aAAa,EACb,QAAQ,EACR,iCAAiC,CACjC,CAAC;gBACF,OAAO;YACR,CAAC;YAKD,IACC,OAAO,CAAC,QAAQ,IAAI,IAAI;gBACxB,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,+BAA+B,CAAC,EACtD,CAAC;gBACF,MAAM,IAAI,CAAC,QAAQ,CAClB,EAAE,EACF,IAAI,EACJ,aAAa,EACb,QAAQ,EACR,0BAA0B,YAAG,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CACnE,CAAC;gBACF,OAAO;YACR,CAAC;YAGD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,CAAC;gBAC/B,GAAG,EAAE,IAAI,yBAAY,CAAC;oBACrB,WAAW,EAAE;wBACZ,EAAE;qBACF;iBACD,CAAC;gBACF,MAAM,EAAE,IAAI,CAAC,+BAA+B,IAAI,EAAE;gBAClD,EAAE;aACF,CAAC,CAAC;YAGH,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YAEd,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC;YAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;gBAAS,CAAC;YACV,IAAI,CAAC,SAAS,EAAE,CAAC;QAClB,CAAC;IACF,CAAC;IAGO,KAAK,CAAC,QAAQ,CACrB,EAAS,EACT,IAAiB,EACjB,aAAmB,EACnB,MAAkB,EAClB,YAAqB;QAErB,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAc;YACvB,gBAAgB,EAAE,aAAa;YAC/B,cAAc,EAAE,IAAI,IAAI,EAAE;YAC1B,MAAM;YACN,aAAa,EAAE,YAAY;YAC3B,GAAG,CAAC,YAAY,IAAI,IAAI,IAAI,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC;SAC5D,CAAC;QAIF,IAAI,MAAM,KAAK,QAAQ,IAAI,YAAY,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YAC9D,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;YAGxB,IAAI,CAAC,gCAAgC;gBACpC,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;QACxC,CAAC;QAGD,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;YACvB,QAAQ,EAAE,MAAM;YAChB,WAAW,EAAE;gBACZ,EAAE;gBACF,GAAG,EAAE,WAAW,CAAC,IAAI;aACrB;YACD,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI;SACJ,CAAC,CAAC;QAIH,IACC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;YAC3C,IAAI,CAAC,kCAAkC,IAAI,IAAI,EAC9C,CAAC;YACF,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;gBACtB,QAAQ,EAAE,MAAM;gBAChB,WAAW,EAAE;oBACZ,EAAE;oBACF,GAAG,EAAE,WAAW,CAAC,IAAI;iBACrB;gBACD,IAAI,EAAE;oBACL,aAAa,EAAE,IAAI,CAAC,aAAa;oBACjC,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;oBAC/C,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;oBACrD,+BAA+B,EAAE,IAAI,CAAC,+BAA+B;oBACrE,kCAAkC,EACjC,IAAI,CAAC,kCAAkC;oBACxC,QAAQ,EAAE,IAAI,CAAC,QAAQ;iBACvB;aACD,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IAGO,kBAAkB,CAAC,OAAe;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QAChE,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;IACrC,CAAC;IAGO,IAAI;QACX,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzE,kBAAS,CAAC,EAAE;aACV,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YACzB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;gBACxB,OAAO;YACR,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,UAAU,CACjC,UAAU,aAAa;;;sCAGU,KAAK;;;;;6EAKkC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;;;;;;YAMhG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;2BAC/B,EACtB,YAAY,CACZ,CAAC;YACF,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAO;YACR,CAAC;YAGD,MAAM,OAAO,CAAC,GAAG,CAChB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;gBAC7B,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,GAAkB,CAAC,CAAC;YAC5C,CAAC,CAAC,CACF,CAAC;YACF,QAAQ,GAAG,IAAI,CAAC;QACjB,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAC;QACjD,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACb,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;IACL,CAAC;IAGM,KAAK;QACX,kBAAS,CAAC,EAAE,CAAC,EAAE,EAAE,CAChB,cAAc,EACd,KAAK,EAAE,GAAG,EAAE,EAAE;YACb,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;gBACvB,MAAM,kBAAS,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;oBAC3C,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,UAAU,CACjC,UAAU,aAAa,sDAAsD,EAC7E,CAAC,GAAG,CAAC,OAAO,CAAC,CACb,CAAC;oBACF,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC5B,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAgB,CAAC,CAAC;oBACvD,CAAC;gBACF,CAAC,CAAC,CAAC;YACJ,CAAC;QACF,CAAC,EACD;YACC,OAAO,EAAP,gBAAO;SACP,CACD,CAAC;QACF,IAAI,CAAC,IAAI,EAAE,CAAC;IACb,CAAC;CACD;AA3ND,wBA2NC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@balena/pinejs",
3
- "version": "16.2.0-build-joshbwlng-tasks-cd1aff5f4bbfacaad189b013578d5cbee51c3932-1",
3
+ "version": "16.2.0-build-joshbwlng-tasks-a83c83b4c78803915d0cb6297cc8cc1862622d08-1",
4
4
  "main": "out/server-glue/module",
5
5
  "type": "commonjs",
6
6
  "repository": "git@github.com:balena-io/pinejs.git",
@@ -12,7 +12,7 @@
12
12
  },
13
13
  "scripts": {
14
14
  "prepublish": "require-npm4-to-publish",
15
- "prepare": "node -e \"try { require('husky').install() } catch (e) {if (e.code !== 'MODULE_NOT_FOUND') throw e}\" && npm run build",
15
+ "prepare": "node -e \"try { (await import('husky')).default() } catch (e) { if (e.code !== 'ERR_MODULE_NOT_FOUND') throw e }\" --input-type module && npm run build",
16
16
  "build": "grunt build",
17
17
  "webpack-browser": "grunt browser",
18
18
  "webpack-module": "grunt module",
@@ -65,7 +65,7 @@
65
65
  "typed-error": "^3.2.2"
66
66
  },
67
67
  "devDependencies": {
68
- "@balena/lint": "^7.2.4",
68
+ "@balena/lint": "^8.0.0",
69
69
  "@faker-js/faker": "^8.3.1",
70
70
  "@types/busboy": "^1.5.3",
71
71
  "@types/chai": "^4.3.11",
@@ -90,7 +90,7 @@
90
90
  "grunt-text-replace": "^0.4.0",
91
91
  "grunt-ts": "^6.0.0-beta.22",
92
92
  "grunt-webpack": "^6.0.0",
93
- "husky": "^8.0.3",
93
+ "husky": "^9.0.0",
94
94
  "json-schema-to-ts": "^3.0.1",
95
95
  "lint-staged": "^15.2.0",
96
96
  "load-grunt-tasks": "^5.1.0",
@@ -147,6 +147,6 @@
147
147
  "recursive": true
148
148
  },
149
149
  "versionist": {
150
- "publishedAt": "2024-04-10T23:12:22.905Z"
150
+ "publishedAt": "2024-04-15T01:28:03.598Z"
151
151
  }
152
152
  }
@@ -37,93 +37,22 @@ export class Worker {
37
37
  this.interval = tasksEnv.queueIntervalMS;
38
38
  }
39
39
 
40
+ // Check if instance can execute more tasks
40
41
  private canExecute(): boolean {
41
42
  return (
42
43
  this.executing < this.concurrency && Object.keys(this.handlers).length > 0
43
44
  );
44
45
  }
45
46
 
46
- private poll(): void {
47
- let executed = false;
48
- const names = Object.keys(this.handlers);
49
- const binds = names.map((_, index) => `$${index + 1}`).join(', ');
50
- sbvrUtils.db
51
- .transaction(async (tx) => {
52
- if (!this.canExecute()) {
53
- return;
54
- }
55
-
56
- const result = await tx.executeSql(
57
- `SELECT ${selectColumns}
58
- FROM task AS t
59
- WHERE
60
- t."is executed by-handler" IN (${binds}) AND
61
- t."status" = 'pending' AND
62
- t."attempt count" <= t."attempt limit" AND
63
- (
64
- t."is scheduled to execute on-time" IS NULL OR
65
- t."is scheduled to execute on-time" <= CURRENT_TIMESTAMP + INTERVAL '${Math.ceil(this.interval / 1000)} second'
66
- )
67
- ORDER BY
68
- t."is scheduled to execute on-time" ASC,
69
- t."priority" DESC,
70
- t."id" ASC
71
- LIMIT ${Math.max(this.concurrency - this.executing, 0)}
72
- FOR UPDATE SKIP LOCKED`,
73
- names,
74
- );
75
- if (result.rows.length === 0) {
76
- return;
77
- }
78
-
79
- // Tasks found, execute them in parallel
80
- await Promise.all(
81
- result.rows.map(async (row) => {
82
- await this.execute(tx, row as PartialTask);
83
- }),
84
- );
85
- executed = true;
86
- })
87
- .catch((err) => {
88
- console.error('Failed polling for tasks:', err);
89
- })
90
- .finally(() => {
91
- setTimeout(() => this.poll(), executed ? 0 : this.interval);
92
- });
93
- }
94
-
95
- // Start listening and polling for tasks
96
- public start() {
97
- sbvrUtils.db.on?.(
98
- 'notification',
99
- async (msg) => {
100
- if (this.canExecute()) {
101
- await sbvrUtils.db.transaction(async (tx) => {
102
- const result = await tx.executeSql(
103
- `SELECT ${selectColumns} FROM task AS t WHERE id = $1 FOR UPDATE SKIP LOCKED`,
104
- [msg.payload],
105
- );
106
- if (result.rows.length > 0) {
107
- await this.execute(tx, result.rows[0] as PartialTask);
108
- }
109
- });
110
- }
111
- },
112
- {
113
- channel,
114
- },
115
- );
116
- this.poll();
117
- }
118
-
47
+ // Execute a task
119
48
  private async execute(tx: Db.Tx, task: PartialTask): Promise<void> {
120
49
  this.executing++;
121
50
  try {
122
- // Get the handler
51
+ // Get specified handler
123
52
  const handler = this.handlers[task.is_executed_by__handler];
124
53
  const startedOnTime = new Date();
125
54
  if (handler == null) {
126
- await this.update(
55
+ await this.finalize(
127
56
  tx,
128
57
  task,
129
58
  startedOnTime,
@@ -140,7 +69,7 @@ export class Worker {
140
69
  handler.validate != null &&
141
70
  !handler.validate(task.is_executed_with__parameter_set)
142
71
  ) {
143
- await this.update(
72
+ await this.finalize(
144
73
  tx,
145
74
  task,
146
75
  startedOnTime,
@@ -150,7 +79,7 @@ export class Worker {
150
79
  return;
151
80
  }
152
81
 
153
- // Execute the handler
82
+ // Execute handler
154
83
  const result = await handler.fn({
155
84
  api: new PinejsClient({
156
85
  passthrough: {
@@ -161,10 +90,10 @@ export class Worker {
161
90
  tx,
162
91
  });
163
92
 
164
- // Update the task with the results
165
- await this.update(tx, task, startedOnTime, result.status, result.error);
93
+ // Update task with results
94
+ await this.finalize(tx, task, startedOnTime, result.status, result.error);
166
95
  } catch (err) {
167
- // This shouldn't normally happen, but if it does, we want to log it and kill the process
96
+ // This shouldn't happen, but if it does we want to log and kill the process
168
97
  console.error('Task execution failed:', err);
169
98
  process.exit(1);
170
99
  } finally {
@@ -172,12 +101,8 @@ export class Worker {
172
101
  }
173
102
  }
174
103
 
175
- private getNextAttemptTime(attempt: number): Date | null {
176
- const delay = Math.ceil(Math.exp(Math.min(10, attempt))) * 1000;
177
- return new Date(Date.now() + delay);
178
- }
179
-
180
- private async update(
104
+ // Update task and schedule next attempt if needed
105
+ private async finalize(
181
106
  tx: Db.Tx,
182
107
  task: PartialTask,
183
108
  startedOnTime: Date,
@@ -238,4 +163,84 @@ export class Worker {
238
163
  });
239
164
  }
240
165
  }
166
+
167
+ // Calculate next attempt time using exponential backoff
168
+ private getNextAttemptTime(attempt: number): Date | null {
169
+ const delay = Math.ceil(Math.exp(Math.min(10, attempt))) * 1000;
170
+ return new Date(Date.now() + delay);
171
+ }
172
+
173
+ // Poll for tasks to execute
174
+ private poll(): void {
175
+ let executed = false;
176
+ const handlerNames = Object.keys(this.handlers);
177
+ const binds = handlerNames.map((_, index) => `$${index + 1}`).join(', ');
178
+ sbvrUtils.db
179
+ .transaction(async (tx) => {
180
+ if (!this.canExecute()) {
181
+ return;
182
+ }
183
+
184
+ const result = await tx.executeSql(
185
+ `SELECT ${selectColumns}
186
+ FROM task AS t
187
+ WHERE
188
+ t."is executed by-handler" IN (${binds}) AND
189
+ t."status" = 'pending' AND
190
+ t."attempt count" <= t."attempt limit" AND
191
+ (
192
+ t."is scheduled to execute on-time" IS NULL OR
193
+ t."is scheduled to execute on-time" <= CURRENT_TIMESTAMP + INTERVAL '${Math.ceil(this.interval / 1000)} second'
194
+ )
195
+ ORDER BY
196
+ t."is scheduled to execute on-time" ASC,
197
+ t."priority" DESC,
198
+ t."id" ASC
199
+ LIMIT ${Math.max(this.concurrency - this.executing, 0)}
200
+ FOR UPDATE SKIP LOCKED`,
201
+ handlerNames,
202
+ );
203
+ if (result.rows.length === 0) {
204
+ return;
205
+ }
206
+
207
+ // Tasks found, execute them in parallel
208
+ await Promise.all(
209
+ result.rows.map(async (row) => {
210
+ await this.execute(tx, row as PartialTask);
211
+ }),
212
+ );
213
+ executed = true;
214
+ })
215
+ .catch((err) => {
216
+ console.error('Failed polling for tasks:', err);
217
+ })
218
+ .finally(() => {
219
+ setTimeout(() => this.poll(), executed ? 0 : this.interval);
220
+ });
221
+ }
222
+
223
+ // Start listening and polling for tasks
224
+ public start(): void {
225
+ sbvrUtils.db.on?.(
226
+ 'notification',
227
+ async (msg) => {
228
+ if (this.canExecute()) {
229
+ await sbvrUtils.db.transaction(async (tx) => {
230
+ const result = await tx.executeSql(
231
+ `SELECT ${selectColumns} FROM task AS t WHERE id = $1 FOR UPDATE SKIP LOCKED`,
232
+ [msg.payload],
233
+ );
234
+ if (result.rows.length > 0) {
235
+ await this.execute(tx, result.rows[0] as PartialTask);
236
+ }
237
+ });
238
+ }
239
+ },
240
+ {
241
+ channel,
242
+ },
243
+ );
244
+ this.poll();
245
+ }
241
246
  }