@tstdl/base 0.92.84 → 0.92.86
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/ai/ai.service.d.ts +1 -1
- package/ai/ai.service.js +34 -16
- package/ai/types.d.ts +1 -1
- package/authentication/authentication.api.d.ts +9 -9
- package/authentication/models/schemas.d.ts +2 -2
- package/cancellation/token.d.ts +1 -1
- package/document-management/api/document-management.api.d.ts +94 -94
- package/document-management/models/document-category.model.d.ts +1 -0
- package/document-management/models/document-index.model.d.ts +7 -0
- package/document-management/models/document-index.model.js +32 -0
- package/document-management/models/document-request-file.model.d.ts +1 -1
- package/document-management/models/document-request-file.model.js +2 -2
- package/document-management/models/document-type.model.d.ts +1 -0
- package/document-management/models/document.model.d.ts +1 -1
- package/document-management/models/document.model.js +2 -2
- package/document-management/models/service-models/document.service-model.d.ts +51 -51
- package/document-management/models/service-models/document.service-model.js +2 -2
- package/document-management/server/drizzle/{0000_sloppy_fenris.sql → 0000_useful_overlord.sql} +2 -2
- package/document-management/server/drizzle/meta/0000_snapshot.json +5 -5
- package/document-management/server/drizzle/meta/_journal.json +2 -2
- package/document-management/server/drizzle.config.js +1 -1
- package/document-management/server/module.d.ts +1 -1
- package/document-management/server/module.js +1 -1
- package/document-management/server/schemas.d.ts +33 -0
- package/document-management/{models → server}/schemas.js +14 -14
- package/document-management/server/services/document-management.service.d.ts +17 -3
- package/document-management/server/services/document-management.service.js +65 -17
- package/examples/orm/schemas.d.ts +1 -1
- package/mail/drizzle.config.js +1 -1
- package/mail/models/schemas.d.ts +1 -1
- package/orm/decorators.d.ts +4 -4
- package/orm/entity.d.ts +5 -7
- package/orm/entity.js +9 -1
- package/orm/index.d.ts +1 -0
- package/orm/index.js +1 -0
- package/orm/query.d.ts +1 -3
- package/orm/query.js +0 -1
- package/orm/repository.types.d.ts +32 -0
- package/orm/repository.types.js +1 -0
- package/orm/server/database-schema.d.ts +4 -4
- package/orm/server/drizzle/schema-converter.d.ts +1 -1
- package/orm/server/index.d.ts +1 -0
- package/orm/server/index.js +1 -0
- package/orm/server/query-converter.d.ts +1 -2
- package/orm/server/query-converter.js +66 -61
- package/orm/server/repository.d.ts +78 -42
- package/orm/server/repository.js +202 -106
- package/orm/server/sqls.d.ts +7 -0
- package/orm/server/sqls.js +6 -0
- package/orm/server/types.d.ts +3 -3
- package/orm/types.d.ts +1 -1
- package/package.json +13 -11
- package/process-shutdown.js +0 -3
- package/queue/enqueue-batch.d.ts +1 -0
- package/queue/enqueue-batch.js +1 -1
- package/queue/mongo/queue.d.ts +9 -4
- package/queue/mongo/queue.js +5 -6
- package/queue/postgres/drizzle/0000_zippy_moondragon.sql +11 -0
- package/queue/postgres/drizzle/meta/0000_snapshot.json +90 -0
- package/queue/postgres/drizzle/meta/_journal.json +13 -0
- package/queue/postgres/drizzle.config.d.ts +2 -0
- package/queue/postgres/drizzle.config.js +11 -0
- package/queue/postgres/index.d.ts +4 -0
- package/queue/postgres/index.js +4 -0
- package/queue/postgres/job.model.d.ts +13 -0
- package/queue/postgres/job.model.js +55 -0
- package/queue/postgres/module.d.ts +9 -0
- package/queue/postgres/module.js +29 -0
- package/queue/postgres/queue.d.ts +28 -0
- package/queue/postgres/queue.js +149 -0
- package/queue/postgres/queue.provider.d.ts +7 -0
- package/queue/postgres/queue.provider.js +21 -0
- package/queue/postgres/schemas.d.ts +3 -0
- package/queue/postgres/schemas.js +4 -0
- package/queue/provider.d.ts +2 -1
- package/queue/queue.d.ts +18 -6
- package/schema/schemas/object.d.ts +1 -1
- package/utils/timing.d.ts +4 -3
- package/utils/timing.js +3 -1
- package/document-management/models/schemas.d.ts +0 -33
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tstdl/base",
|
|
3
|
-
"version": "0.92.
|
|
3
|
+
"version": "0.92.86",
|
|
4
4
|
"author": "Patrick Hein",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -17,14 +17,16 @@
|
|
|
17
17
|
"pub": "npm run build:production && rm -vf dist/test* && rm -vrf dist/tools/ && npm publish dist/",
|
|
18
18
|
"tsc:watch": "tsc --watch",
|
|
19
19
|
"tsc-alias:watch": "tsc-alias --watch",
|
|
20
|
-
"generate:
|
|
21
|
-
"generate:
|
|
22
|
-
"generate:
|
|
23
|
-
"generate:
|
|
24
|
-
"
|
|
25
|
-
"copy:
|
|
26
|
-
"copy:
|
|
27
|
-
"copy:
|
|
20
|
+
"generate:migration": "npm run generate:migration:document-management && npm run generate:migration:authentication && npm run generate:migration:mail && npm run generate:migration:queue",
|
|
21
|
+
"generate:migration:document-management": "drizzle-kit generate --config dist/document-management/server/drizzle.config.js",
|
|
22
|
+
"generate:migration:authentication": "drizzle-kit generate --config dist/authentication/server/drizzle.config.js",
|
|
23
|
+
"generate:migration:mail": "drizzle-kit generate --config dist/mail/drizzle.config.js",
|
|
24
|
+
"generate:migration:queue": "drizzle-kit generate --config dist/queue/postgres/drizzle.config.js",
|
|
25
|
+
"copy:orm": "npm run copy:orm:document-management && npm run copy:orm:authentication && npm run copy:orm:mail && npm run copy:orm:queue",
|
|
26
|
+
"copy:orm:document-management": "rm -rf ./dist/document-management/server/drizzle && cp -r ./source/document-management/server/drizzle ./dist/document-management/server/",
|
|
27
|
+
"copy:orm:authentication": "rm -rf ./dist/authentication/server/drizzle && cp -r ./source/authentication/server/drizzle ./dist/authentication/server/",
|
|
28
|
+
"copy:orm:mail": "rm -rf ./dist/mail/drizzle && cp -r ./source/mail/drizzle ./dist/mail/",
|
|
29
|
+
"copy:orm:queue": "rm -rf ./dist/queue/postgres/drizzle && cp -r ./source/queue/postgres/drizzle ./dist/queue/postgres/"
|
|
28
30
|
},
|
|
29
31
|
"exports": {
|
|
30
32
|
"./tsconfig.json": "./tsconfig.json",
|
|
@@ -136,7 +138,7 @@
|
|
|
136
138
|
"type-fest": "4.35"
|
|
137
139
|
},
|
|
138
140
|
"devDependencies": {
|
|
139
|
-
"@stylistic/eslint-plugin": "4.
|
|
141
|
+
"@stylistic/eslint-plugin": "4.1",
|
|
140
142
|
"@types/chroma-js": "2.4",
|
|
141
143
|
"@types/koa__router": "12.0",
|
|
142
144
|
"@types/luxon": "3.4",
|
|
@@ -162,7 +164,7 @@
|
|
|
162
164
|
"@zxcvbn-ts/language-de": "^3.0",
|
|
163
165
|
"@zxcvbn-ts/language-en": "^3.0",
|
|
164
166
|
"chroma-js": "^2.6",
|
|
165
|
-
"drizzle-orm": "^0.
|
|
167
|
+
"drizzle-orm": "^0.40",
|
|
166
168
|
"handlebars": "^4.7",
|
|
167
169
|
"minio": "^8.0",
|
|
168
170
|
"mjml": "^4.15",
|
package/process-shutdown.js
CHANGED
|
@@ -14,7 +14,6 @@ export function getShutdownSignal() {
|
|
|
14
14
|
return getShutdownToken().signal;
|
|
15
15
|
}
|
|
16
16
|
let logger;
|
|
17
|
-
// eslint-disable-next-line no-shadow
|
|
18
17
|
export function setProcessShutdownLogger(shutdownLogger) {
|
|
19
18
|
logger = shutdownLogger;
|
|
20
19
|
}
|
|
@@ -49,7 +48,6 @@ export function initializeSignals() {
|
|
|
49
48
|
}
|
|
50
49
|
});
|
|
51
50
|
for (const event of quitEvents) {
|
|
52
|
-
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
|
53
51
|
process.on(event, (...args) => {
|
|
54
52
|
console.error(event, ...args);
|
|
55
53
|
quitReason = args;
|
|
@@ -57,7 +55,6 @@ export function initializeSignals() {
|
|
|
57
55
|
});
|
|
58
56
|
}
|
|
59
57
|
for (const quitSignal of quitSignals) {
|
|
60
|
-
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
|
61
58
|
process.on(quitSignal, (signal) => {
|
|
62
59
|
logger.info(`${signal} received, quitting.`);
|
|
63
60
|
requestShutdown();
|
package/queue/enqueue-batch.d.ts
CHANGED
|
@@ -13,4 +13,5 @@ export declare class QueueEnqueueBatch<T> implements QueueEnqueueBatchMethods<T>
|
|
|
13
13
|
/** enqueues all added items */
|
|
14
14
|
enqueue(returnJobs?: false): Promise<void>;
|
|
15
15
|
enqueue(returnJobs: true): Promise<Job<T>[]>;
|
|
16
|
+
enqueue(returnJobs?: boolean): Promise<Job<T>[] | undefined>;
|
|
16
17
|
}
|
package/queue/enqueue-batch.js
CHANGED
|
@@ -13,7 +13,7 @@ export class QueueEnqueueBatch {
|
|
|
13
13
|
async enqueue(returnJobs) {
|
|
14
14
|
const items = this.items;
|
|
15
15
|
this.items = [];
|
|
16
|
-
const result = await this.queue.enqueueMany(items, returnJobs);
|
|
16
|
+
const result = await this.queue.enqueueMany(items, { returnJobs });
|
|
17
17
|
return result;
|
|
18
18
|
}
|
|
19
19
|
}
|
package/queue/mongo/queue.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CancellationSignal } from '../../cancellation/index.js';
|
|
2
2
|
import { Lock } from '../../lock/index.js';
|
|
3
3
|
import { MessageBusProvider } from '../../message-bus/index.js';
|
|
4
|
-
import type { EnqueueManyItem,
|
|
4
|
+
import type { EnqueueManyItem, EnqueueManyOptions, EnqueueOneOptions, Job, JobTag } from '../../queue/index.js';
|
|
5
5
|
import { Queue, type QueueConfig } from '../../queue/index.js';
|
|
6
6
|
import { MongoJobRepository } from './mongo-job.repository.js';
|
|
7
7
|
export declare class MongoQueue<T = unknown> extends Queue<T> {
|
|
@@ -12,9 +12,14 @@ export declare class MongoQueue<T = unknown> extends Queue<T> {
|
|
|
12
12
|
private readonly maxTries;
|
|
13
13
|
private readonly messageBus;
|
|
14
14
|
constructor(repository: MongoJobRepository<T>, lock: Lock, messageBusProvider: MessageBusProvider, key: string, config?: QueueConfig);
|
|
15
|
-
enqueue(data: T, options?:
|
|
16
|
-
enqueueMany(items: EnqueueManyItem<T>[],
|
|
17
|
-
|
|
15
|
+
enqueue(data: T, options?: EnqueueOneOptions): Promise<Job<T>>;
|
|
16
|
+
enqueueMany(items: EnqueueManyItem<T>[], options?: EnqueueManyOptions & {
|
|
17
|
+
returnJobs?: false;
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
enqueueMany(items: EnqueueManyItem<T>[], options: EnqueueManyOptions & {
|
|
20
|
+
returnJobs: true;
|
|
21
|
+
}): Promise<Job<T>[]>;
|
|
22
|
+
enqueueMany(items: EnqueueManyItem<T>[], options?: EnqueueManyOptions): Promise<void | Job<T>[]>;
|
|
18
23
|
has(id: string): Promise<boolean>;
|
|
19
24
|
countByTag(tag: JobTag): Promise<number>;
|
|
20
25
|
get(id: string): Promise<Job<T> | undefined>;
|
package/queue/mongo/queue.js
CHANGED
|
@@ -66,12 +66,12 @@ let MongoQueue = class MongoQueue extends Queue {
|
|
|
66
66
|
: await this.repository.insertWithUniqueTagStrategy(newJob, uniqueTag);
|
|
67
67
|
return toModelJob(job);
|
|
68
68
|
}
|
|
69
|
-
async enqueueMany(items,
|
|
69
|
+
async enqueueMany(items, options) {
|
|
70
70
|
const now = currentTimestamp();
|
|
71
71
|
const nonUnique = [];
|
|
72
72
|
const keepOld = [];
|
|
73
73
|
const takeNew = [];
|
|
74
|
-
for (const { data, tag = null,
|
|
74
|
+
for (const { data, tag = null, priority = defaultJobPriority } of items) {
|
|
75
75
|
const newMongoJob = {
|
|
76
76
|
queue: this.queueKey,
|
|
77
77
|
jobId: getNewId(),
|
|
@@ -83,7 +83,7 @@ let MongoQueue = class MongoQueue extends Queue {
|
|
|
83
83
|
lastDequeueTimestamp: 0,
|
|
84
84
|
batch: null
|
|
85
85
|
};
|
|
86
|
-
switch (uniqueTag) {
|
|
86
|
+
switch (options?.uniqueTag) {
|
|
87
87
|
case undefined:
|
|
88
88
|
nonUnique.push(newMongoJob);
|
|
89
89
|
break;
|
|
@@ -102,7 +102,7 @@ let MongoQueue = class MongoQueue extends Queue {
|
|
|
102
102
|
(keepOld.length > 0) ? this.repository.bulkInsertWithUniqueTagStrategy(keepOld, UniqueTagStrategy.KeepOld) : undefined,
|
|
103
103
|
(takeNew.length > 0) ? this.repository.bulkInsertWithUniqueTagStrategy(takeNew, UniqueTagStrategy.TakeNew) : undefined
|
|
104
104
|
]);
|
|
105
|
-
if (returnJobs) {
|
|
105
|
+
if (options?.returnJobs == true) {
|
|
106
106
|
const keepOldTags = keepOld.map((job) => job.tag);
|
|
107
107
|
const takeNewTags = takeNew.map((job) => job.tag);
|
|
108
108
|
const uniqueTagJobs = await this.repository.loadManyByFilter({ queue: this.queueKey, tag: { $in: [...keepOldTags, ...takeNewTags] } });
|
|
@@ -225,7 +225,7 @@ MongoQueue = __decorate([
|
|
|
225
225
|
if (isString(argument)) {
|
|
226
226
|
return provider.get(argument, defaultQueueConfig);
|
|
227
227
|
}
|
|
228
|
-
return provider.get(argument.
|
|
228
|
+
return provider.get(argument.name, { ...defaultQueueConfig, ...argument });
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
231
|
}),
|
|
@@ -241,7 +241,6 @@ function toModelJob(mongoJob) {
|
|
|
241
241
|
};
|
|
242
242
|
return job;
|
|
243
243
|
}
|
|
244
|
-
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
245
244
|
function getDequeueFindParameters(queueKey, maxTries, processTimeout, batch = null) {
|
|
246
245
|
const now = currentTimestamp();
|
|
247
246
|
const maximumLastDequeueTimestamp = now - processTimeout;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
CREATE TABLE "queue"."job" (
|
|
2
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
3
|
+
"queue" text NOT NULL,
|
|
4
|
+
"tag" text,
|
|
5
|
+
"priority" integer NOT NULL,
|
|
6
|
+
"enqueue_timestamp" timestamp with time zone NOT NULL,
|
|
7
|
+
"tries" integer NOT NULL,
|
|
8
|
+
"last_dequeue_timestamp" timestamp with time zone,
|
|
9
|
+
"data" jsonb NOT NULL,
|
|
10
|
+
CONSTRAINT "job_queue_tag_unique" UNIQUE("queue","tag")
|
|
11
|
+
);
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "1a2e63a5-b780-4f4d-ae41-ce8369aa1cf0",
|
|
3
|
+
"prevId": "00000000-0000-0000-0000-000000000000",
|
|
4
|
+
"version": "7",
|
|
5
|
+
"dialect": "postgresql",
|
|
6
|
+
"tables": {
|
|
7
|
+
"queue.job": {
|
|
8
|
+
"name": "job",
|
|
9
|
+
"schema": "queue",
|
|
10
|
+
"columns": {
|
|
11
|
+
"id": {
|
|
12
|
+
"name": "id",
|
|
13
|
+
"type": "uuid",
|
|
14
|
+
"primaryKey": true,
|
|
15
|
+
"notNull": true,
|
|
16
|
+
"default": "gen_random_uuid()"
|
|
17
|
+
},
|
|
18
|
+
"queue": {
|
|
19
|
+
"name": "queue",
|
|
20
|
+
"type": "text",
|
|
21
|
+
"primaryKey": false,
|
|
22
|
+
"notNull": true
|
|
23
|
+
},
|
|
24
|
+
"tag": {
|
|
25
|
+
"name": "tag",
|
|
26
|
+
"type": "text",
|
|
27
|
+
"primaryKey": false,
|
|
28
|
+
"notNull": false
|
|
29
|
+
},
|
|
30
|
+
"priority": {
|
|
31
|
+
"name": "priority",
|
|
32
|
+
"type": "integer",
|
|
33
|
+
"primaryKey": false,
|
|
34
|
+
"notNull": true
|
|
35
|
+
},
|
|
36
|
+
"enqueue_timestamp": {
|
|
37
|
+
"name": "enqueue_timestamp",
|
|
38
|
+
"type": "timestamp with time zone",
|
|
39
|
+
"primaryKey": false,
|
|
40
|
+
"notNull": true
|
|
41
|
+
},
|
|
42
|
+
"tries": {
|
|
43
|
+
"name": "tries",
|
|
44
|
+
"type": "integer",
|
|
45
|
+
"primaryKey": false,
|
|
46
|
+
"notNull": true
|
|
47
|
+
},
|
|
48
|
+
"last_dequeue_timestamp": {
|
|
49
|
+
"name": "last_dequeue_timestamp",
|
|
50
|
+
"type": "timestamp with time zone",
|
|
51
|
+
"primaryKey": false,
|
|
52
|
+
"notNull": false
|
|
53
|
+
},
|
|
54
|
+
"data": {
|
|
55
|
+
"name": "data",
|
|
56
|
+
"type": "jsonb",
|
|
57
|
+
"primaryKey": false,
|
|
58
|
+
"notNull": true
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"indexes": {},
|
|
62
|
+
"foreignKeys": {},
|
|
63
|
+
"compositePrimaryKeys": {},
|
|
64
|
+
"uniqueConstraints": {
|
|
65
|
+
"job_queue_tag_unique": {
|
|
66
|
+
"name": "job_queue_tag_unique",
|
|
67
|
+
"nullsNotDistinct": false,
|
|
68
|
+
"columns": [
|
|
69
|
+
"queue",
|
|
70
|
+
"tag"
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"policies": {},
|
|
75
|
+
"checkConstraints": {},
|
|
76
|
+
"isRLSEnabled": false
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"enums": {},
|
|
80
|
+
"schemas": {},
|
|
81
|
+
"sequences": {},
|
|
82
|
+
"roles": {},
|
|
83
|
+
"policies": {},
|
|
84
|
+
"views": {},
|
|
85
|
+
"_meta": {
|
|
86
|
+
"columns": {},
|
|
87
|
+
"schemas": {},
|
|
88
|
+
"tables": {}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { relative, resolve } from 'node:path';
|
|
2
|
+
import { defineConfig } from 'drizzle-kit';
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
dialect: 'postgresql',
|
|
5
|
+
out: relative('./', resolve(__dirname, './drizzle/').replace('dist', 'source')),
|
|
6
|
+
schema: resolve(__dirname, './schemas.js'),
|
|
7
|
+
migrations: {
|
|
8
|
+
schema: 'queue',
|
|
9
|
+
table: '_migrations'
|
|
10
|
+
}
|
|
11
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EntityWithoutMetadata } from '../../orm/entity.js';
|
|
2
|
+
import { Integer, Json, Timestamp } from '../../orm/index.js';
|
|
3
|
+
import type { ObjectLiteral } from '../../types.js';
|
|
4
|
+
import type { Job } from '../queue.js';
|
|
5
|
+
export declare class PostgresJob<T extends ObjectLiteral = ObjectLiteral> extends EntityWithoutMetadata implements Job<T> {
|
|
6
|
+
queue: string;
|
|
7
|
+
tag: string | null;
|
|
8
|
+
priority: Integer;
|
|
9
|
+
enqueueTimestamp: Timestamp;
|
|
10
|
+
tries: Integer;
|
|
11
|
+
lastDequeueTimestamp: Timestamp | null;
|
|
12
|
+
data: Json<T>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Table } from '../../orm/decorators.js';
|
|
11
|
+
import { EntityWithoutMetadata } from '../../orm/entity.js';
|
|
12
|
+
import { Integer, Json, Timestamp, Unique } from '../../orm/index.js';
|
|
13
|
+
import { StringProperty } from '../../schema/index.js';
|
|
14
|
+
let PostgresJob = class PostgresJob extends EntityWithoutMetadata {
|
|
15
|
+
queue;
|
|
16
|
+
tag;
|
|
17
|
+
priority;
|
|
18
|
+
enqueueTimestamp;
|
|
19
|
+
tries;
|
|
20
|
+
lastDequeueTimestamp;
|
|
21
|
+
data;
|
|
22
|
+
};
|
|
23
|
+
__decorate([
|
|
24
|
+
StringProperty(),
|
|
25
|
+
__metadata("design:type", String)
|
|
26
|
+
], PostgresJob.prototype, "queue", void 0);
|
|
27
|
+
__decorate([
|
|
28
|
+
StringProperty({ nullable: true }),
|
|
29
|
+
__metadata("design:type", Object)
|
|
30
|
+
], PostgresJob.prototype, "tag", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
Integer(),
|
|
33
|
+
__metadata("design:type", Number)
|
|
34
|
+
], PostgresJob.prototype, "priority", void 0);
|
|
35
|
+
__decorate([
|
|
36
|
+
Timestamp(),
|
|
37
|
+
__metadata("design:type", Number)
|
|
38
|
+
], PostgresJob.prototype, "enqueueTimestamp", void 0);
|
|
39
|
+
__decorate([
|
|
40
|
+
Integer(),
|
|
41
|
+
__metadata("design:type", Number)
|
|
42
|
+
], PostgresJob.prototype, "tries", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
Timestamp({ nullable: true }),
|
|
45
|
+
__metadata("design:type", Object)
|
|
46
|
+
], PostgresJob.prototype, "lastDequeueTimestamp", void 0);
|
|
47
|
+
__decorate([
|
|
48
|
+
Json(),
|
|
49
|
+
__metadata("design:type", Object)
|
|
50
|
+
], PostgresJob.prototype, "data", void 0);
|
|
51
|
+
PostgresJob = __decorate([
|
|
52
|
+
Table('job'),
|
|
53
|
+
Unique(['queue', 'tag'])
|
|
54
|
+
], PostgresJob);
|
|
55
|
+
export { PostgresJob };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type DatabaseConfig } from '../../orm/server/index.js';
|
|
2
|
+
export declare class PostgresQueueModuleConfig {
|
|
3
|
+
database?: DatabaseConfig;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* configure mail module
|
|
7
|
+
*/
|
|
8
|
+
export declare function configurePostgresQueue(config: PostgresQueueModuleConfig, register?: boolean): void;
|
|
9
|
+
export declare function migratePostgresQueueSchema(): Promise<void>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { inject } from '../../injector/index.js';
|
|
2
|
+
import { Injector } from '../../injector/injector.js';
|
|
3
|
+
import { Database, migrate } from '../../orm/server/index.js';
|
|
4
|
+
import { QueueProvider } from '../provider.js';
|
|
5
|
+
import { Queue } from '../queue.js';
|
|
6
|
+
import { PostgresQueue } from './queue.js';
|
|
7
|
+
import { PostgresQueueProvider } from './queue.provider.js';
|
|
8
|
+
export class PostgresQueueModuleConfig {
|
|
9
|
+
database;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* configure mail module
|
|
13
|
+
*/
|
|
14
|
+
export function configurePostgresQueue(config, register = true) {
|
|
15
|
+
Injector.register(PostgresQueueModuleConfig, { useValue: config });
|
|
16
|
+
if (register) {
|
|
17
|
+
Injector.registerSingleton(QueueProvider, { useToken: PostgresQueueProvider });
|
|
18
|
+
Injector.registerSingleton(Queue, { useToken: PostgresQueue });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export async function migratePostgresQueueSchema() {
|
|
22
|
+
const connection = inject(PostgresQueueModuleConfig, undefined, { optional: true })?.database?.connection;
|
|
23
|
+
const database = inject(Database, connection);
|
|
24
|
+
await migrate(database, {
|
|
25
|
+
migrationsSchema: 'queue',
|
|
26
|
+
migrationsTable: '_migrations',
|
|
27
|
+
migrationsFolder: import.meta.resolve('./drizzle').replace('file://', '')
|
|
28
|
+
});
|
|
29
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { CancellationSignal } from '../../cancellation/index.js';
|
|
2
|
+
import type { ObjectLiteral } from '../../types.js';
|
|
3
|
+
import { Queue, type EnqueueManyItem, type EnqueueManyOptions, type EnqueueOneOptions, type Job, type JobTag } from '../queue.js';
|
|
4
|
+
export declare class PostgresQueue<T extends ObjectLiteral> extends Queue<T> {
|
|
5
|
+
#private;
|
|
6
|
+
enqueue(data: T, options?: EnqueueOneOptions): Promise<Job<T>>;
|
|
7
|
+
enqueueMany(items: EnqueueManyItem<T>[], options?: EnqueueManyOptions & {
|
|
8
|
+
returnJobs?: false;
|
|
9
|
+
}): Promise<void>;
|
|
10
|
+
enqueueMany(items: EnqueueManyItem<T>[], options: EnqueueManyOptions & {
|
|
11
|
+
returnJobs: true;
|
|
12
|
+
}): Promise<Job<T>[]>;
|
|
13
|
+
enqueueMany(items: EnqueueManyItem<T>[], options?: EnqueueManyOptions): Promise<Job<T>[] | undefined>;
|
|
14
|
+
has(id: string): Promise<boolean>;
|
|
15
|
+
countByTag(tag: JobTag): Promise<number>;
|
|
16
|
+
get(id: string): Promise<Job<T> | undefined>;
|
|
17
|
+
getByTag(tag: JobTag): Promise<Job<T>[]>;
|
|
18
|
+
cancel(id: string): Promise<void>;
|
|
19
|
+
cancelMany(ids: string[]): Promise<void>;
|
|
20
|
+
cancelByTag(tag: JobTag): Promise<void>;
|
|
21
|
+
cancelByTags(tags: JobTag[]): Promise<void>;
|
|
22
|
+
dequeue(): Promise<Job<T> | undefined>;
|
|
23
|
+
dequeueMany(count: number): Promise<Job<T>[]>;
|
|
24
|
+
acknowledge(job: Job<T>): Promise<void>;
|
|
25
|
+
acknowledgeMany(jobs: Job<T>[]): Promise<void>;
|
|
26
|
+
getConsumer(cancellationSignal: CancellationSignal): AsyncIterableIterator<Job<T>>;
|
|
27
|
+
getBatchConsumer(size: number, cancellationSignal: CancellationSignal): AsyncIterableIterator<Job<T>[]>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { and, asc, eq, inArray, isNull as isSqlNull, lt, lte, or, sql } from 'drizzle-orm';
|
|
8
|
+
import { merge } from 'rxjs';
|
|
9
|
+
import { CancellationSignal } from '../../cancellation/index.js';
|
|
10
|
+
import { inject, injectArgument, provide, Singleton } from '../../injector/index.js';
|
|
11
|
+
import { MessageBus } from '../../message-bus/index.js';
|
|
12
|
+
import { DatabaseConfig, EntityRepositoryConfig, injectRepository, interval, RANDOM_UUID, TRANSACTION_TIMESTAMP } from '../../orm/server/index.js';
|
|
13
|
+
import { cancelableTimeout } from '../../utils/timing.js';
|
|
14
|
+
import { isString } from '../../utils/type-guards.js';
|
|
15
|
+
import { millisecondsPerSecond } from '../../utils/units.js';
|
|
16
|
+
import { defaultQueueConfig, Queue, UniqueTagStrategy } from '../queue.js';
|
|
17
|
+
import { PostgresJob } from './job.model.js';
|
|
18
|
+
import { PostgresQueueModuleConfig } from './module.js';
|
|
19
|
+
import { job } from './schemas.js';
|
|
20
|
+
let PostgresQueue = class PostgresQueue extends Queue {
|
|
21
|
+
#repository = injectRepository(PostgresJob);
|
|
22
|
+
#config = injectArgument(this);
|
|
23
|
+
#processTimeout = (isString(this.#config) ? undefined : this.#config.processTimeout) ?? defaultQueueConfig.processTimeout;
|
|
24
|
+
#maxTries = (isString(this.#config) ? undefined : this.#config.maxTries) ?? defaultQueueConfig.maxTries;
|
|
25
|
+
#queueName = isString(this.#config) ? this.#config : this.#config.name;
|
|
26
|
+
#messageBus = inject((MessageBus), `PostgresQueue:${this.#queueName}`);
|
|
27
|
+
#keepOldUpdate = { id: sql `${job.id}` };
|
|
28
|
+
#takeNewUpdate = {
|
|
29
|
+
id: RANDOM_UUID,
|
|
30
|
+
queue: this.#queueName,
|
|
31
|
+
priority: sql `excluded.priority`,
|
|
32
|
+
tag: sql `excluded.tag`,
|
|
33
|
+
tries: 0,
|
|
34
|
+
enqueueTimestamp: TRANSACTION_TIMESTAMP,
|
|
35
|
+
lastDequeueTimestamp: null,
|
|
36
|
+
data: sql `excluded.data`
|
|
37
|
+
};
|
|
38
|
+
#dequeueQuery = and(eq(job.queue, this.#queueName), lt(job.tries, this.#maxTries), or(isSqlNull(job.lastDequeueTimestamp), lte(job.lastDequeueTimestamp, sql `${job.lastDequeueTimestamp} + ${interval(this.#processTimeout, 'milliseconds')}`)));
|
|
39
|
+
#dequeueUpdate = {
|
|
40
|
+
tries: sql `${job.tries} + 1`,
|
|
41
|
+
lastDequeueTimestamp: TRANSACTION_TIMESTAMP
|
|
42
|
+
};
|
|
43
|
+
async enqueue(data, options) {
|
|
44
|
+
const jobs = await this.enqueueMany([{ data, tag: options?.tag, priority: options?.priority }], { returnJobs: true });
|
|
45
|
+
return jobs[0];
|
|
46
|
+
}
|
|
47
|
+
async enqueueMany(items, options) {
|
|
48
|
+
const newEntities = items.map((item) => ({
|
|
49
|
+
queue: this.#queueName,
|
|
50
|
+
priority: item.priority ?? 1000,
|
|
51
|
+
tag: item.tag ?? null,
|
|
52
|
+
tries: 0,
|
|
53
|
+
enqueueTimestamp: TRANSACTION_TIMESTAMP,
|
|
54
|
+
lastDequeueTimestamp: null,
|
|
55
|
+
data: item.data
|
|
56
|
+
}));
|
|
57
|
+
const update = (options?.uniqueTag == UniqueTagStrategy.TakeNew)
|
|
58
|
+
? this.#takeNewUpdate
|
|
59
|
+
: this.#keepOldUpdate;
|
|
60
|
+
const jobs = await this.#repository.upsertMany(['queue', 'tag'], newEntities, update);
|
|
61
|
+
this.#messageBus.publishAndForget();
|
|
62
|
+
return jobs;
|
|
63
|
+
}
|
|
64
|
+
async has(id) {
|
|
65
|
+
return this.#repository.hasByQuery({ queue: this.#queueName, id });
|
|
66
|
+
}
|
|
67
|
+
async countByTag(tag) {
|
|
68
|
+
return this.#repository.countByQuery({ queue: this.#queueName, tag });
|
|
69
|
+
}
|
|
70
|
+
async get(id) {
|
|
71
|
+
return this.#repository.tryLoadByQuery({ queue: this.#queueName, id });
|
|
72
|
+
}
|
|
73
|
+
async getByTag(tag) {
|
|
74
|
+
return this.#repository.loadManyByQuery({ queue: this.#queueName, tag });
|
|
75
|
+
}
|
|
76
|
+
async cancel(id) {
|
|
77
|
+
await this.#repository.hardDeleteByQuery({ queue: this.#queueName, id });
|
|
78
|
+
}
|
|
79
|
+
async cancelMany(ids) {
|
|
80
|
+
await this.#repository.hardDeleteManyByQuery({ queue: this.#queueName, id: { $in: ids } });
|
|
81
|
+
}
|
|
82
|
+
async cancelByTag(tag) {
|
|
83
|
+
await this.#repository.hardDeleteByQuery({ queue: this.#queueName, tag });
|
|
84
|
+
}
|
|
85
|
+
async cancelByTags(tags) {
|
|
86
|
+
await this.#repository.hardDeleteManyByQuery({ queue: this.#queueName, tag: { $in: tags } });
|
|
87
|
+
}
|
|
88
|
+
async dequeue() {
|
|
89
|
+
const jobs = await this.dequeueMany(1);
|
|
90
|
+
if (jobs.length == 0) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
return jobs[0];
|
|
94
|
+
}
|
|
95
|
+
async dequeueMany(count) {
|
|
96
|
+
const rows = await this.#repository.session
|
|
97
|
+
.update(job)
|
|
98
|
+
.set(this.#dequeueUpdate)
|
|
99
|
+
.where(inArray(job.id, this.#repository.session.select({ id: job.id })
|
|
100
|
+
.from(job)
|
|
101
|
+
.where(this.#dequeueQuery)
|
|
102
|
+
.orderBy(asc(job.priority), asc(job.enqueueTimestamp), asc(job.lastDequeueTimestamp), asc(job.tries))
|
|
103
|
+
.limit(count)))
|
|
104
|
+
.returning();
|
|
105
|
+
return this.#repository.$mapManyToEntity(rows); // eslint-disable-line @typescript-eslint/no-unsafe-argument
|
|
106
|
+
}
|
|
107
|
+
async acknowledge(job) {
|
|
108
|
+
return this.cancel(job.id);
|
|
109
|
+
}
|
|
110
|
+
async acknowledgeMany(jobs) {
|
|
111
|
+
const ids = jobs.map((job) => job.id);
|
|
112
|
+
return this.cancelMany(ids);
|
|
113
|
+
}
|
|
114
|
+
async *getConsumer(cancellationSignal) {
|
|
115
|
+
const continue$ = merge(this.#messageBus.allMessages$, cancellationSignal);
|
|
116
|
+
while (cancellationSignal.isUnset) {
|
|
117
|
+
const job = await this.dequeue();
|
|
118
|
+
if (job != undefined) {
|
|
119
|
+
yield job;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
const cancelled = await cancelableTimeout(5 * millisecondsPerSecond, continue$);
|
|
123
|
+
if (cancelled) {
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async *getBatchConsumer(size, cancellationSignal) {
|
|
130
|
+
const continue$ = merge(this.#messageBus.allMessages$, cancellationSignal);
|
|
131
|
+
while (cancellationSignal.isUnset) {
|
|
132
|
+
const jobs = await this.dequeueMany(size);
|
|
133
|
+
if (jobs.length > 0) {
|
|
134
|
+
yield jobs;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
await cancelableTimeout(5 * millisecondsPerSecond, continue$);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
PostgresQueue = __decorate([
|
|
142
|
+
Singleton({
|
|
143
|
+
providers: [
|
|
144
|
+
provide(EntityRepositoryConfig, { useValue: { schema: 'queue' } }),
|
|
145
|
+
provide(DatabaseConfig, { useFactory: (_, context) => context.resolve(PostgresQueueModuleConfig).database ?? context.resolve(DatabaseConfig, undefined, { skipSelf: true }) })
|
|
146
|
+
]
|
|
147
|
+
})
|
|
148
|
+
], PostgresQueue);
|
|
149
|
+
export { PostgresQueue };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { QueueProvider, type QueueConfig } from '../../queue/index.js';
|
|
2
|
+
import type { ObjectLiteral } from '../../types.js';
|
|
3
|
+
import { PostgresQueue } from './queue.js';
|
|
4
|
+
export declare class PostgresQueueProvider extends QueueProvider {
|
|
5
|
+
#private;
|
|
6
|
+
get<T extends ObjectLiteral>(name: string, config?: QueueConfig): PostgresQueue<T>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { Singleton } from '../../injector/decorators.js';
|
|
8
|
+
import { inject } from '../../injector/inject.js';
|
|
9
|
+
import { Injector } from '../../injector/injector.js';
|
|
10
|
+
import { QueueProvider } from '../../queue/index.js';
|
|
11
|
+
import { PostgresQueue } from './queue.js';
|
|
12
|
+
let PostgresQueueProvider = class PostgresQueueProvider extends QueueProvider {
|
|
13
|
+
#injector = inject(Injector);
|
|
14
|
+
get(name, config) {
|
|
15
|
+
return this.#injector.resolve((PostgresQueue), { ...config, name: name });
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
PostgresQueueProvider = __decorate([
|
|
19
|
+
Singleton()
|
|
20
|
+
], PostgresQueueProvider);
|
|
21
|
+
export { PostgresQueueProvider };
|