@balena/pinejs 16.2.0-build-joshbwlng-tasks-1297814070f10e99d7bd475c28c365cc03081096-3 → 16.2.0-build-joshbwlng-tasks-009b08b1f157611c22f2425c25f905d5a59aaabe-1
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/.pinejs-cache.json +1 -1
- package/.versionbot/CHANGELOG.yml +9 -1
- package/CHANGELOG.md +2 -1
- package/out/tasks/index.d.ts +1 -1
- package/out/tasks/index.js +51 -14
- package/out/tasks/index.js.map +1 -1
- package/out/tasks/model.sbvr +1 -1
- package/out/tasks/types.d.ts +1 -1
- package/out/tasks/types.js +2 -2
- package/out/tasks/types.js.map +1 -1
- package/out/tasks/worker.js +19 -19
- package/out/tasks/worker.js.map +1 -1
- package/package.json +2 -2
- package/src/tasks/index.ts +89 -17
- package/src/tasks/model.sbvr +1 -1
- package/src/tasks/types.ts +2 -2
- package/src/tasks/worker.ts +19 -19
@@ -1,4 +1,12 @@
|
|
1
1
|
- commits:
|
2
|
+
- subject: Cleanup
|
3
|
+
hash: 009b08b1f157611c22f2425c25f905d5a59aaabe
|
4
|
+
body: ""
|
5
|
+
footer:
|
6
|
+
Change-type: patch
|
7
|
+
change-type: patch
|
8
|
+
author: Josh Bowling
|
9
|
+
nested: []
|
2
10
|
- subject: Add async tasks
|
3
11
|
hash: 1297814070f10e99d7bd475c28c365cc03081096
|
4
12
|
body: ""
|
@@ -9,7 +17,7 @@
|
|
9
17
|
nested: []
|
10
18
|
version: 16.2.0
|
11
19
|
title: ""
|
12
|
-
date: 2024-04-
|
20
|
+
date: 2024-04-30T05:37:15.944Z
|
13
21
|
- commits:
|
14
22
|
- subject: Update @balena/odata-to-abstract-sql to 6.2.7
|
15
23
|
hash: 76b2f842af0b49ef2956db23a22758fc0d1e50a0
|
package/CHANGELOG.md
CHANGED
@@ -5,8 +5,9 @@ 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-
|
8
|
+
## (2024-04-30)
|
9
9
|
|
10
|
+
* Cleanup [Josh Bowling]
|
10
11
|
* Add async tasks [Josh Bowling]
|
11
12
|
|
12
13
|
# v16.1.3
|
package/out/tasks/index.d.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import type { Schema } from 'ajv';
|
2
2
|
import type * as Db from '../database-layer/db';
|
3
|
-
import
|
3
|
+
import * as sbvrUtils from '../sbvr-api/sbvr-utils';
|
4
4
|
import type { TaskHandler } from './types';
|
5
5
|
export * from './types';
|
6
6
|
export declare const config: {
|
package/out/tasks/index.js
CHANGED
@@ -32,6 +32,7 @@ const env_1 = require("../config-loader/env");
|
|
32
32
|
const errors_1 = require("../sbvr-api/errors");
|
33
33
|
const hooks_1 = require("../sbvr-api/hooks");
|
34
34
|
const sbvr_utils_1 = require("../sbvr-api/sbvr-utils");
|
35
|
+
const sbvrUtils = __importStar(require("../sbvr-api/sbvr-utils"));
|
35
36
|
const common_1 = require("./common");
|
36
37
|
const worker_1 = require("./worker");
|
37
38
|
__exportStar(require("./types"), exports);
|
@@ -48,20 +49,54 @@ exports.config = {
|
|
48
49
|
};
|
49
50
|
async function createTrigger(tx) {
|
50
51
|
await tx.executeSql(`
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
52
|
+
CREATE OR REPLACE FUNCTION notify_task_insert()
|
53
|
+
RETURNS TRIGGER AS $$
|
54
|
+
BEGIN
|
55
|
+
PERFORM pg_notify('${common_1.channel}', NEW.id::text);
|
56
|
+
RETURN NEW;
|
57
|
+
END;
|
58
|
+
$$ LANGUAGE plpgsql;
|
59
|
+
`);
|
59
60
|
await tx.executeSql(`
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
61
|
+
CREATE OR REPLACE TRIGGER task_insert_trigger
|
62
|
+
AFTER INSERT ON task
|
63
|
+
FOR EACH ROW WHEN (NEW.status = 'queued' AND NEW."is scheduled to execute on-time" IS NULL)
|
64
|
+
EXECUTE FUNCTION notify_task_insert();
|
65
|
+
`);
|
66
|
+
}
|
67
|
+
async function createIndexes(tx) {
|
68
|
+
await tx.executeSql(`
|
69
|
+
CREATE INDEX IF NOT EXISTS idx_task_poll ON task USING btree (
|
70
|
+
"is executed by-handler",
|
71
|
+
"is scheduled to execute on-time" ASC,
|
72
|
+
"priority" DESC,
|
73
|
+
"id" ASC
|
74
|
+
) WHERE status = 'queued';
|
75
|
+
`);
|
76
|
+
await tx.executeSql(`
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_task_queued ON task (
|
78
|
+
"id",
|
79
|
+
"is created by-actor"
|
80
|
+
) WHERE status = 'queued';
|
81
|
+
`);
|
82
|
+
}
|
83
|
+
async function adjustPriority(actor, priority) {
|
84
|
+
const result = await sbvrUtils.db.executeSql(`SELECT "is created by-actor", COUNT("id") AS task_count
|
85
|
+
FROM (
|
86
|
+
SELECT "id", "is created by-actor"
|
87
|
+
FROM task
|
88
|
+
WHERE "status" = 'queued'
|
89
|
+
ORDER BY "id" DESC
|
90
|
+
LIMIT 100
|
91
|
+
) AS recent_tasks
|
92
|
+
GROUP BY "is created by-actor"
|
93
|
+
ORDER BY task_count DESC;
|
94
|
+
`);
|
95
|
+
if (result.rows.some((row) => parseInt(row.task_count, 10) >= 49 &&
|
96
|
+
row['is created by-actor'] !== actor)) {
|
97
|
+
return priority + 1;
|
98
|
+
}
|
99
|
+
return priority;
|
65
100
|
}
|
66
101
|
let worker = null;
|
67
102
|
async function setup(db, tx) {
|
@@ -69,6 +104,7 @@ async function setup(db, tx) {
|
|
69
104
|
return;
|
70
105
|
}
|
71
106
|
await createTrigger(tx);
|
107
|
+
await createIndexes(tx);
|
72
108
|
const client = new sbvr_utils_1.PinejsClient({
|
73
109
|
apiPrefix: `/${common_1.apiRoot}/`,
|
74
110
|
});
|
@@ -80,10 +116,11 @@ async function setup(db, tx) {
|
|
80
116
|
if (request.values.is_created_by__actor == null) {
|
81
117
|
throw new errors_1.BadRequestError('Creating tasks with missing actor on req is not allowed');
|
82
118
|
}
|
83
|
-
request.values.status = '
|
119
|
+
request.values.status = 'queued';
|
84
120
|
request.values.attempt_count = 0;
|
85
121
|
request.values.priority ??= 1;
|
86
122
|
request.values.attempt_limit ??= 1;
|
123
|
+
request.values.priority = await adjustPriority(request.values.is_created_by__actor, request.values.priority);
|
87
124
|
if (request.values.is_scheduled_with__cron_expression != null &&
|
88
125
|
request.values.is_scheduled_to_execute_on__time == null) {
|
89
126
|
try {
|
package/out/tasks/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tasks/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,wDAA0C;AAC1C,8CAAyD;AAEzD,+CAAqD;AACrD,6CAAgD;AAChD,uDAAsD;
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tasks/index.ts"],"names":[],"mappings":"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"}
|
package/out/tasks/model.sbvr
CHANGED
@@ -45,7 +45,7 @@ Fact type: task is scheduled to execute on time
|
|
45
45
|
Necessity: each task is scheduled to execute on at most one time
|
46
46
|
Fact type: task has status
|
47
47
|
Necessity: each task has exactly one status
|
48
|
-
Definition: "
|
48
|
+
Definition: "queued" or "cancelled" or "succeeded" or "failed"
|
49
49
|
Fact type: task started on time
|
50
50
|
Necessity: each task started on at most one time
|
51
51
|
Fact type: task ended on time
|
package/out/tasks/types.d.ts
CHANGED
@@ -2,7 +2,7 @@ import type { ValidateFunction } from 'ajv';
|
|
2
2
|
import type { AnyObject } from 'pinejs-client-core';
|
3
3
|
import type * as Db from '../database-layer/db';
|
4
4
|
import type { PinejsClient } from '../sbvr-api/sbvr-utils';
|
5
|
-
export declare const taskStatuses: readonly ["
|
5
|
+
export declare const taskStatuses: readonly ["queued", "cancelled", "succeeded", "failed"];
|
6
6
|
export type TaskStatus = (typeof taskStatuses)[number];
|
7
7
|
export interface Task {
|
8
8
|
id: number;
|
package/out/tasks/types.js
CHANGED
package/out/tasks/types.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tasks/types.ts"],"names":[],"mappings":";;;AAKa,QAAA,YAAY,GAAG;IAC3B,
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tasks/types.ts"],"names":[],"mappings":";;;AAKa,QAAA,YAAY,GAAG;IAC3B,QAAQ;IACR,WAAW;IACX,WAAW;IACX,QAAQ;CACC,CAAC"}
|
package/out/tasks/worker.js
CHANGED
@@ -67,7 +67,7 @@ class Worker {
|
|
67
67
|
await this.finalize(tx, task, startedOnTime, 'failed', `Invalid parameter set: ${common_1.ajv.errorsText(handler.validate.errors)}`);
|
68
68
|
return;
|
69
69
|
}
|
70
|
-
let status = '
|
70
|
+
let status = 'queued';
|
71
71
|
let error;
|
72
72
|
try {
|
73
73
|
await module_1.sbvrUtils.db.transaction(async (handlerTx) => {
|
@@ -82,7 +82,7 @@ class Worker {
|
|
82
82
|
});
|
83
83
|
status = results.status;
|
84
84
|
error = results.error;
|
85
|
-
if (results.status !== '
|
85
|
+
if (results.status !== 'succeeded' && !handlerTx.isClosed()) {
|
86
86
|
await handlerTx.rollback();
|
87
87
|
}
|
88
88
|
});
|
@@ -114,7 +114,7 @@ class Worker {
|
|
114
114
|
...(errorMessage != null && { error_message: errorMessage }),
|
115
115
|
};
|
116
116
|
if (status === 'failed' && attemptCount < task.attempt_limit) {
|
117
|
-
body.status = '
|
117
|
+
body.status = 'queued';
|
118
118
|
body.is_scheduled_to_execute_on__time =
|
119
119
|
this.getNextAttemptTime(attemptCount);
|
120
120
|
}
|
@@ -127,7 +127,7 @@ class Worker {
|
|
127
127
|
id: task.id,
|
128
128
|
body,
|
129
129
|
});
|
130
|
-
if (['failed', '
|
130
|
+
if (['failed', 'succeeded'].includes(body.status) &&
|
131
131
|
task.is_scheduled_with__cron_expression != null) {
|
132
132
|
await this.client.post({
|
133
133
|
resource: 'task',
|
@@ -160,21 +160,21 @@ class Worker {
|
|
160
160
|
return;
|
161
161
|
}
|
162
162
|
const result = await tx.executeSql(`SELECT ${selectColumns}
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
163
|
+
FROM task AS t
|
164
|
+
WHERE
|
165
|
+
t."is executed by-handler" IN (${binds}) AND
|
166
|
+
t."status" = 'queued' AND
|
167
|
+
t."attempt count" <= t."attempt limit" AND
|
168
|
+
(
|
169
|
+
t."is scheduled to execute on-time" IS NULL OR
|
170
|
+
t."is scheduled to execute on-time" <= CURRENT_TIMESTAMP + INTERVAL '${Math.ceil(this.interval / 1000)} second'
|
171
|
+
)
|
172
|
+
ORDER BY
|
173
|
+
t."is scheduled to execute on-time" ASC,
|
174
|
+
t."priority" DESC,
|
175
|
+
t."id" ASC
|
176
|
+
LIMIT ${Math.max(this.concurrency - this.executing, 0)}
|
177
|
+
FOR UPDATE SKIP LOCKED`, handlerNames);
|
178
178
|
if (result.rows.length === 0) {
|
179
179
|
return;
|
180
180
|
}
|
package/out/tasks/worker.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/tasks/worker.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AACA,8CAAyD;AAEzD,6CAA8D;AAC9D,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,IAAI,MAAM,GAAe,
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/tasks/worker.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@balena/pinejs",
|
3
|
-
"version": "16.2.0-build-joshbwlng-tasks-
|
3
|
+
"version": "16.2.0-build-joshbwlng-tasks-009b08b1f157611c22f2425c25f905d5a59aaabe-1",
|
4
4
|
"main": "out/server-glue/module",
|
5
5
|
"type": "commonjs",
|
6
6
|
"repository": "git@github.com:balena-io/pinejs.git",
|
@@ -147,6 +147,6 @@
|
|
147
147
|
"recursive": true
|
148
148
|
},
|
149
149
|
"versionist": {
|
150
|
-
"publishedAt": "2024-04-
|
150
|
+
"publishedAt": "2024-04-30T05:37:16.724Z"
|
151
151
|
}
|
152
152
|
}
|
package/src/tasks/index.ts
CHANGED
@@ -5,7 +5,7 @@ import type * as Db from '../database-layer/db';
|
|
5
5
|
import { BadRequestError } from '../sbvr-api/errors';
|
6
6
|
import { addPureHook } from '../sbvr-api/hooks';
|
7
7
|
import { PinejsClient } from '../sbvr-api/sbvr-utils';
|
8
|
-
import
|
8
|
+
import * as sbvrUtils from '../sbvr-api/sbvr-utils';
|
9
9
|
import { ajv, apiRoot, channel } from './common';
|
10
10
|
import type { TaskHandler } from './types';
|
11
11
|
import { Worker } from './worker';
|
@@ -30,22 +30,85 @@ export const config = {
|
|
30
30
|
// Only poll or execute on triggers if worker is not already at max concurrency
|
31
31
|
async function createTrigger(tx: Db.Tx): Promise<void> {
|
32
32
|
await tx.executeSql(`
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
// Only trigger if task is
|
33
|
+
CREATE OR REPLACE FUNCTION notify_task_insert()
|
34
|
+
RETURNS TRIGGER AS $$
|
35
|
+
BEGIN
|
36
|
+
PERFORM pg_notify('${channel}', NEW.id::text);
|
37
|
+
RETURN NEW;
|
38
|
+
END;
|
39
|
+
$$ LANGUAGE plpgsql;
|
40
|
+
`);
|
41
|
+
|
42
|
+
// Only trigger if task is queued and not scheduled
|
43
43
|
await tx.executeSql(`
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
44
|
+
CREATE OR REPLACE TRIGGER task_insert_trigger
|
45
|
+
AFTER INSERT ON task
|
46
|
+
FOR EACH ROW WHEN (NEW.status = 'queued' AND NEW."is scheduled to execute on-time" IS NULL)
|
47
|
+
EXECUTE FUNCTION notify_task_insert();
|
48
|
+
`);
|
49
|
+
}
|
50
|
+
|
51
|
+
// Create indexes
|
52
|
+
async function createIndexes(tx: Db.Tx): Promise<void> {
|
53
|
+
// Partial index for polling
|
54
|
+
await tx.executeSql(`
|
55
|
+
CREATE INDEX IF NOT EXISTS idx_task_poll ON task USING btree (
|
56
|
+
"is executed by-handler",
|
57
|
+
"is scheduled to execute on-time" ASC,
|
58
|
+
"priority" DESC,
|
59
|
+
"id" ASC
|
60
|
+
) WHERE status = 'queued';
|
61
|
+
`);
|
62
|
+
|
63
|
+
// Partial index used to adjust priority based on actor
|
64
|
+
await tx.executeSql(`
|
65
|
+
CREATE INDEX IF NOT EXISTS idx_task_queued ON task (
|
66
|
+
"id",
|
67
|
+
"is created by-actor"
|
68
|
+
) WHERE status = 'queued';
|
69
|
+
`);
|
70
|
+
}
|
71
|
+
|
72
|
+
// Check if a task should be given priority
|
73
|
+
// This is used to balance the load across actors
|
74
|
+
// by giving priority to actors with less tasks in the queue
|
75
|
+
// when another actor is crossing a percentage threshold of queued tasks
|
76
|
+
// This is to prevent a single actor from hogging the queue
|
77
|
+
async function adjustPriority(
|
78
|
+
actor: number,
|
79
|
+
priority: number,
|
80
|
+
): Promise<number> {
|
81
|
+
const result = await (sbvrUtils.db.executeSql(
|
82
|
+
`SELECT "is created by-actor", COUNT("id") AS task_count
|
83
|
+
FROM (
|
84
|
+
SELECT "id", "is created by-actor"
|
85
|
+
FROM task
|
86
|
+
WHERE "status" = 'queued'
|
87
|
+
ORDER BY "id" DESC
|
88
|
+
LIMIT 100
|
89
|
+
) AS recent_tasks
|
90
|
+
GROUP BY "is created by-actor"
|
91
|
+
ORDER BY task_count DESC;
|
92
|
+
`,
|
93
|
+
) as Promise<{
|
94
|
+
rowsAffected: number;
|
95
|
+
rows: Array<{
|
96
|
+
'is created by-actor': number;
|
97
|
+
task_count: string;
|
98
|
+
}>;
|
99
|
+
}>);
|
100
|
+
|
101
|
+
// Increase the priority of this task if another actor is filling up the queue
|
102
|
+
if (
|
103
|
+
result.rows.some(
|
104
|
+
(row) =>
|
105
|
+
parseInt(row.task_count, 10) >= 49 &&
|
106
|
+
row['is created by-actor'] !== actor,
|
107
|
+
)
|
108
|
+
) {
|
109
|
+
return priority + 1;
|
110
|
+
}
|
111
|
+
return priority;
|
49
112
|
}
|
50
113
|
|
51
114
|
let worker: Worker | null = null;
|
@@ -58,6 +121,9 @@ export async function setup(db: Db.Database, tx: Db.Tx): Promise<void> {
|
|
58
121
|
// Create trigger function if it doesn't exist
|
59
122
|
await createTrigger(tx);
|
60
123
|
|
124
|
+
// Create indexes if they don't exist
|
125
|
+
await createIndexes(tx);
|
126
|
+
|
61
127
|
const client = new PinejsClient({
|
62
128
|
apiPrefix: `/${apiRoot}/`,
|
63
129
|
});
|
@@ -76,11 +142,17 @@ export async function setup(db: Db.Database, tx: Db.Tx): Promise<void> {
|
|
76
142
|
}
|
77
143
|
|
78
144
|
// Set defaults
|
79
|
-
request.values.status = '
|
145
|
+
request.values.status = 'queued';
|
80
146
|
request.values.attempt_count = 0;
|
81
147
|
request.values.priority ??= 1;
|
82
148
|
request.values.attempt_limit ??= 1;
|
83
149
|
|
150
|
+
// Possibly adjust priority based on actor
|
151
|
+
request.values.priority = await adjustPriority(
|
152
|
+
request.values.is_created_by__actor,
|
153
|
+
request.values.priority,
|
154
|
+
);
|
155
|
+
|
84
156
|
// Set scheduled start time using cron expression if provided
|
85
157
|
if (
|
86
158
|
request.values.is_scheduled_with__cron_expression != null &&
|
package/src/tasks/model.sbvr
CHANGED
@@ -45,7 +45,7 @@ Fact type: task is scheduled to execute on time
|
|
45
45
|
Necessity: each task is scheduled to execute on at most one time
|
46
46
|
Fact type: task has status
|
47
47
|
Necessity: each task has exactly one status
|
48
|
-
Definition: "
|
48
|
+
Definition: "queued" or "cancelled" or "succeeded" or "failed"
|
49
49
|
Fact type: task started on time
|
50
50
|
Necessity: each task started on at most one time
|
51
51
|
Fact type: task ended on time
|
package/src/tasks/types.ts
CHANGED
@@ -4,9 +4,9 @@ import type * as Db from '../database-layer/db';
|
|
4
4
|
import type { PinejsClient } from '../sbvr-api/sbvr-utils';
|
5
5
|
|
6
6
|
export const taskStatuses = [
|
7
|
-
'
|
7
|
+
'queued',
|
8
8
|
'cancelled',
|
9
|
-
'
|
9
|
+
'succeeded',
|
10
10
|
'failed',
|
11
11
|
] as const;
|
12
12
|
export type TaskStatus = (typeof taskStatuses)[number];
|
package/src/tasks/worker.ts
CHANGED
@@ -81,7 +81,7 @@ export class Worker {
|
|
81
81
|
}
|
82
82
|
|
83
83
|
// Execute handler
|
84
|
-
let status: TaskStatus = '
|
84
|
+
let status: TaskStatus = 'queued';
|
85
85
|
let error: string | undefined;
|
86
86
|
try {
|
87
87
|
await sbvrUtils.db.transaction(async (handlerTx) => {
|
@@ -96,7 +96,7 @@ export class Worker {
|
|
96
96
|
});
|
97
97
|
status = results.status;
|
98
98
|
error = results.error;
|
99
|
-
if (results.status !== '
|
99
|
+
if (results.status !== 'succeeded' && !handlerTx.isClosed()) {
|
100
100
|
await handlerTx.rollback();
|
101
101
|
}
|
102
102
|
});
|
@@ -138,7 +138,7 @@ export class Worker {
|
|
138
138
|
// Re-enqueue if the task failed but has retries left, remember that
|
139
139
|
// attemptCount includes the initial attempt while attempt_limit does not
|
140
140
|
if (status === 'failed' && attemptCount < task.attempt_limit) {
|
141
|
-
body.status = '
|
141
|
+
body.status = 'queued';
|
142
142
|
|
143
143
|
// Schedule next attempt using exponential backoff
|
144
144
|
body.is_scheduled_to_execute_on__time =
|
@@ -159,7 +159,7 @@ export class Worker {
|
|
159
159
|
// Create new task with same configuration if previous
|
160
160
|
// iteration completed and has a cron expression
|
161
161
|
if (
|
162
|
-
['failed', '
|
162
|
+
['failed', 'succeeded'].includes(body.status) &&
|
163
163
|
task.is_scheduled_with__cron_expression != null
|
164
164
|
) {
|
165
165
|
await this.client.post({
|
@@ -200,21 +200,21 @@ export class Worker {
|
|
200
200
|
|
201
201
|
const result = await tx.executeSql(
|
202
202
|
`SELECT ${selectColumns}
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
203
|
+
FROM task AS t
|
204
|
+
WHERE
|
205
|
+
t."is executed by-handler" IN (${binds}) AND
|
206
|
+
t."status" = 'queued' AND
|
207
|
+
t."attempt count" <= t."attempt limit" AND
|
208
|
+
(
|
209
|
+
t."is scheduled to execute on-time" IS NULL OR
|
210
|
+
t."is scheduled to execute on-time" <= CURRENT_TIMESTAMP + INTERVAL '${Math.ceil(this.interval / 1000)} second'
|
211
|
+
)
|
212
|
+
ORDER BY
|
213
|
+
t."is scheduled to execute on-time" ASC,
|
214
|
+
t."priority" DESC,
|
215
|
+
t."id" ASC
|
216
|
+
LIMIT ${Math.max(this.concurrency - this.executing, 0)}
|
217
|
+
FOR UPDATE SKIP LOCKED`,
|
218
218
|
handlerNames,
|
219
219
|
);
|
220
220
|
if (result.rows.length === 0) {
|