@betterinternship/core 2.16.7 → 2.16.8
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 +26 -26
- package/dist/lib/broker/base.process.d.ts +2 -2
- package/dist/lib/broker/base.process.js +2 -2
- package/dist/lib/broker/base.task.d.ts +40 -40
- package/dist/lib/broker/base.task.js +87 -87
- package/dist/lib/broker/broker.d.ts +28 -28
- package/dist/lib/broker/broker.js +111 -111
- package/dist/lib/broker/index.d.ts +2 -2
- package/dist/lib/broker/index.js +2 -2
- package/dist/lib/forms/field-preset-templates.js +8 -8
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +79 -78
package/README.md
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
# Package.Core
|
|
2
|
-
|
|
3
|
-
Contains dependencies shared between the different services of the site.
|
|
4
|
-
|
|
5
|
-
## How to update
|
|
6
|
-
|
|
7
|
-
1. Build the package:
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm run build
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
2. Commit the build:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
git add .
|
|
17
|
-
git commit -m "<follow conventional commits, k thanks>"
|
|
18
|
-
git push
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
3. Update the version and publish the package to NPM:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
npm version <patch|minor|major>
|
|
25
|
-
npm publish
|
|
26
|
-
```
|
|
1
|
+
# Package.Core
|
|
2
|
+
|
|
3
|
+
Contains dependencies shared between the different services of the site.
|
|
4
|
+
|
|
5
|
+
## How to update
|
|
6
|
+
|
|
7
|
+
1. Build the package:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm run build
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. Commit the build:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
git add .
|
|
17
|
+
git commit -m "<follow conventional commits, k thanks>"
|
|
18
|
+
git push
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
3. Update the version and publish the package to NPM:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm version <patch|minor|major>
|
|
25
|
+
npm publish
|
|
26
|
+
```
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare class BaseProcess {
|
|
2
|
-
}
|
|
1
|
+
export declare class BaseProcess {
|
|
2
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export class BaseProcess {
|
|
2
|
-
}
|
|
1
|
+
export class BaseProcess {
|
|
2
|
+
}
|
|
3
3
|
//# sourceMappingURL=base.process.js.map
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
import { Task, Process } from '@betterinternship/db';
|
|
2
|
-
import { JsonValue } from '@prisma/client/runtime/client';
|
|
3
|
-
export interface BaseJson {
|
|
4
|
-
[key: string]: any;
|
|
5
|
-
}
|
|
6
|
-
export declare class TaskRequest<TaskInputs extends JsonValue> implements Pick<Task, 'inputs' | 'internal_id' | 'handler_id' | 'parent_id' | 'process_id' | 'timestamp'> {
|
|
7
|
-
inputs: TaskInputs;
|
|
8
|
-
internal_id: string;
|
|
9
|
-
handler_id: string;
|
|
10
|
-
parent_id: string | null;
|
|
11
|
-
process_id: string;
|
|
12
|
-
timestamp: Date;
|
|
13
|
-
}
|
|
14
|
-
export declare class TaskResponse<TaskResult extends JsonValue> implements Pick<Task, 'result' | 'status' | 'error'> {
|
|
15
|
-
result: TaskResult;
|
|
16
|
-
error: string;
|
|
17
|
-
status: string;
|
|
18
|
-
}
|
|
19
|
-
type TaskResponseHandler<TaskResult extends JsonValue> = (response: TaskResponse<TaskResult>) => Promise<void>;
|
|
20
|
-
export declare class BaseTaskInitiator<TaskInputs extends JsonValue, TaskResult extends JsonValue> {
|
|
21
|
-
private handlerId;
|
|
22
|
-
private requestQueueId;
|
|
23
|
-
private responseQueueId;
|
|
24
|
-
constructor(queueId: string, handler: TaskResponseHandler<TaskResult>);
|
|
25
|
-
init(handler: TaskResponseHandler<TaskResult>): Promise<void>;
|
|
26
|
-
sendTaskRequest(process: Process, inputs: TaskInputs, options: {
|
|
27
|
-
internalId?: string;
|
|
28
|
-
parentId?: string;
|
|
29
|
-
maxRetries?: number;
|
|
30
|
-
}): Promise<boolean>;
|
|
31
|
-
}
|
|
32
|
-
type TaskRequestHandler<TaskInputs extends JsonValue, TaskResult extends JsonValue> = (task: TaskRequest<TaskInputs>) => Promise<TaskResponse<TaskResult>>;
|
|
33
|
-
export declare class BaseTaskRunner<TaskInputs extends JsonValue, TaskResult extends JsonValue> {
|
|
34
|
-
private requestQueueId;
|
|
35
|
-
private responseQueueId;
|
|
36
|
-
private handler;
|
|
37
|
-
constructor(queueId: string, handler: TaskRequestHandler<TaskInputs, TaskResult>);
|
|
38
|
-
listen(processName?: string): Promise<void>;
|
|
39
|
-
}
|
|
40
|
-
export {};
|
|
1
|
+
import { Task, Process } from '@betterinternship/db';
|
|
2
|
+
import { JsonValue } from '@prisma/client/runtime/client';
|
|
3
|
+
export interface BaseJson {
|
|
4
|
+
[key: string]: any;
|
|
5
|
+
}
|
|
6
|
+
export declare class TaskRequest<TaskInputs extends JsonValue> implements Pick<Task, 'inputs' | 'internal_id' | 'handler_id' | 'parent_id' | 'process_id' | 'timestamp'> {
|
|
7
|
+
inputs: TaskInputs;
|
|
8
|
+
internal_id: string;
|
|
9
|
+
handler_id: string;
|
|
10
|
+
parent_id: string | null;
|
|
11
|
+
process_id: string;
|
|
12
|
+
timestamp: Date;
|
|
13
|
+
}
|
|
14
|
+
export declare class TaskResponse<TaskResult extends JsonValue> implements Pick<Task, 'result' | 'status' | 'error'> {
|
|
15
|
+
result: TaskResult;
|
|
16
|
+
error: string;
|
|
17
|
+
status: string;
|
|
18
|
+
}
|
|
19
|
+
type TaskResponseHandler<TaskResult extends JsonValue> = (response: TaskResponse<TaskResult>) => Promise<void>;
|
|
20
|
+
export declare class BaseTaskInitiator<TaskInputs extends JsonValue, TaskResult extends JsonValue> {
|
|
21
|
+
private handlerId;
|
|
22
|
+
private requestQueueId;
|
|
23
|
+
private responseQueueId;
|
|
24
|
+
constructor(queueId: string, handler: TaskResponseHandler<TaskResult>);
|
|
25
|
+
init(handler: TaskResponseHandler<TaskResult>): Promise<void>;
|
|
26
|
+
sendTaskRequest(process: Process, inputs: TaskInputs, options: {
|
|
27
|
+
internalId?: string;
|
|
28
|
+
parentId?: string;
|
|
29
|
+
maxRetries?: number;
|
|
30
|
+
}): Promise<boolean>;
|
|
31
|
+
}
|
|
32
|
+
type TaskRequestHandler<TaskInputs extends JsonValue, TaskResult extends JsonValue> = (task: TaskRequest<TaskInputs>) => Promise<TaskResponse<TaskResult>>;
|
|
33
|
+
export declare class BaseTaskRunner<TaskInputs extends JsonValue, TaskResult extends JsonValue> {
|
|
34
|
+
private requestQueueId;
|
|
35
|
+
private responseQueueId;
|
|
36
|
+
private handler;
|
|
37
|
+
constructor(queueId: string, handler: TaskRequestHandler<TaskInputs, TaskResult>);
|
|
38
|
+
listen(processName?: string): Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
export {};
|
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
import { BrokerAPI } from './broker.js';
|
|
2
|
-
import { tasks } from '@betterinternship/db';
|
|
3
|
-
import { v4 } from 'uuid';
|
|
4
|
-
export class TaskRequest {
|
|
5
|
-
inputs;
|
|
6
|
-
internal_id;
|
|
7
|
-
handler_id;
|
|
8
|
-
parent_id;
|
|
9
|
-
process_id;
|
|
10
|
-
timestamp;
|
|
11
|
-
}
|
|
12
|
-
export class TaskResponse {
|
|
13
|
-
result;
|
|
14
|
-
error;
|
|
15
|
-
status;
|
|
16
|
-
}
|
|
17
|
-
export class BaseTaskInitiator {
|
|
18
|
-
handlerId;
|
|
19
|
-
requestQueueId;
|
|
20
|
-
responseQueueId;
|
|
21
|
-
constructor(queueId, handler) {
|
|
22
|
-
this.handlerId = queueId;
|
|
23
|
-
this.requestQueueId = `request.${queueId}`;
|
|
24
|
-
this.responseQueueId = `response.${queueId}`;
|
|
25
|
-
void this.init(handler);
|
|
26
|
-
}
|
|
27
|
-
async init(handler) {
|
|
28
|
-
const brokerAPI = await BrokerAPI.instance();
|
|
29
|
-
return await brokerAPI.registerQueueHandler(this.responseQueueId, async (taskId) => {
|
|
30
|
-
const task = await tasks.findFirst({ where: { id: taskId } });
|
|
31
|
-
await handler({
|
|
32
|
-
result: task?.result,
|
|
33
|
-
error: task?.error ?? '',
|
|
34
|
-
status: task?.status ?? 'failed',
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
async sendTaskRequest(process, inputs, options) {
|
|
39
|
-
const brokerAPI = await BrokerAPI.instance();
|
|
40
|
-
const task = await tasks.create({
|
|
41
|
-
data: {
|
|
42
|
-
internal_id: options.internalId ?? `${process.id}.${v4()}`,
|
|
43
|
-
parent_id: options.parentId,
|
|
44
|
-
handler_id: this.handlerId,
|
|
45
|
-
process_id: process.id,
|
|
46
|
-
process_name: process.name,
|
|
47
|
-
inputs: inputs,
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
return brokerAPI.addToQueue(this.requestQueueId, task.id, options);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
export class BaseTaskRunner {
|
|
54
|
-
requestQueueId;
|
|
55
|
-
responseQueueId;
|
|
56
|
-
handler;
|
|
57
|
-
constructor(queueId, handler) {
|
|
58
|
-
this.requestQueueId = `request.${queueId}`;
|
|
59
|
-
this.responseQueueId = `response.${queueId}`;
|
|
60
|
-
this.handler = handler;
|
|
61
|
-
}
|
|
62
|
-
async listen(processName) {
|
|
63
|
-
const taskRunner = async (taskId, actions) => {
|
|
64
|
-
const task = await tasks.findFirst({ where: { id: taskId } });
|
|
65
|
-
if (processName && processName !== task?.process_name)
|
|
66
|
-
return;
|
|
67
|
-
if (task?.parent_id && !task?.inputs)
|
|
68
|
-
return actions.hold();
|
|
69
|
-
const response = await this.handler(task);
|
|
70
|
-
await tasks.update({
|
|
71
|
-
where: { id: taskId },
|
|
72
|
-
data: {
|
|
73
|
-
result: response.result ?? {},
|
|
74
|
-
error: response.error ?? '',
|
|
75
|
-
status: response.status,
|
|
76
|
-
},
|
|
77
|
-
});
|
|
78
|
-
if (response.error)
|
|
79
|
-
actions.reject();
|
|
80
|
-
else
|
|
81
|
-
actions.resolve();
|
|
82
|
-
await brokerAPI.addToQueue(this.responseQueueId, taskId);
|
|
83
|
-
};
|
|
84
|
-
const brokerAPI = await BrokerAPI.instance();
|
|
85
|
-
await brokerAPI.registerQueueHandler(this.requestQueueId, taskRunner);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
1
|
+
import { BrokerAPI } from './broker.js';
|
|
2
|
+
import { tasks } from '@betterinternship/db';
|
|
3
|
+
import { v4 } from 'uuid';
|
|
4
|
+
export class TaskRequest {
|
|
5
|
+
inputs;
|
|
6
|
+
internal_id;
|
|
7
|
+
handler_id;
|
|
8
|
+
parent_id;
|
|
9
|
+
process_id;
|
|
10
|
+
timestamp;
|
|
11
|
+
}
|
|
12
|
+
export class TaskResponse {
|
|
13
|
+
result;
|
|
14
|
+
error;
|
|
15
|
+
status;
|
|
16
|
+
}
|
|
17
|
+
export class BaseTaskInitiator {
|
|
18
|
+
handlerId;
|
|
19
|
+
requestQueueId;
|
|
20
|
+
responseQueueId;
|
|
21
|
+
constructor(queueId, handler) {
|
|
22
|
+
this.handlerId = queueId;
|
|
23
|
+
this.requestQueueId = `request.${queueId}`;
|
|
24
|
+
this.responseQueueId = `response.${queueId}`;
|
|
25
|
+
void this.init(handler);
|
|
26
|
+
}
|
|
27
|
+
async init(handler) {
|
|
28
|
+
const brokerAPI = await BrokerAPI.instance();
|
|
29
|
+
return await brokerAPI.registerQueueHandler(this.responseQueueId, async (taskId) => {
|
|
30
|
+
const task = await tasks.findFirst({ where: { id: taskId } });
|
|
31
|
+
await handler({
|
|
32
|
+
result: task?.result,
|
|
33
|
+
error: task?.error ?? '',
|
|
34
|
+
status: task?.status ?? 'failed',
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
async sendTaskRequest(process, inputs, options) {
|
|
39
|
+
const brokerAPI = await BrokerAPI.instance();
|
|
40
|
+
const task = await tasks.create({
|
|
41
|
+
data: {
|
|
42
|
+
internal_id: options.internalId ?? `${process.id}.${v4()}`,
|
|
43
|
+
parent_id: options.parentId,
|
|
44
|
+
handler_id: this.handlerId,
|
|
45
|
+
process_id: process.id,
|
|
46
|
+
process_name: process.name,
|
|
47
|
+
inputs: inputs,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
return brokerAPI.addToQueue(this.requestQueueId, task.id, options);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export class BaseTaskRunner {
|
|
54
|
+
requestQueueId;
|
|
55
|
+
responseQueueId;
|
|
56
|
+
handler;
|
|
57
|
+
constructor(queueId, handler) {
|
|
58
|
+
this.requestQueueId = `request.${queueId}`;
|
|
59
|
+
this.responseQueueId = `response.${queueId}`;
|
|
60
|
+
this.handler = handler;
|
|
61
|
+
}
|
|
62
|
+
async listen(processName) {
|
|
63
|
+
const taskRunner = async (taskId, actions) => {
|
|
64
|
+
const task = await tasks.findFirst({ where: { id: taskId } });
|
|
65
|
+
if (processName && processName !== task?.process_name)
|
|
66
|
+
return;
|
|
67
|
+
if (task?.parent_id && !task?.inputs)
|
|
68
|
+
return actions.hold();
|
|
69
|
+
const response = await this.handler(task);
|
|
70
|
+
await tasks.update({
|
|
71
|
+
where: { id: taskId },
|
|
72
|
+
data: {
|
|
73
|
+
result: response.result ?? {},
|
|
74
|
+
error: response.error ?? '',
|
|
75
|
+
status: response.status,
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
if (response.error)
|
|
79
|
+
actions.reject();
|
|
80
|
+
else
|
|
81
|
+
actions.resolve();
|
|
82
|
+
await brokerAPI.addToQueue(this.responseQueueId, taskId);
|
|
83
|
+
};
|
|
84
|
+
const brokerAPI = await BrokerAPI.instance();
|
|
85
|
+
await brokerAPI.registerQueueHandler(this.requestQueueId, taskRunner);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
88
|
//# sourceMappingURL=base.task.js.map
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import * as amqp from 'amqplib';
|
|
2
|
-
export declare const Q: (...args: string[]) => string;
|
|
3
|
-
export interface RequestBody {
|
|
4
|
-
taskId: string;
|
|
5
|
-
}
|
|
6
|
-
export type TaskResolver = () => void;
|
|
7
|
-
export type TaskRejecter = () => void;
|
|
8
|
-
export type TaskHolder = () => void;
|
|
9
|
-
export type TaskHandler<T> = (taskId: string, actions: {
|
|
10
|
-
resolve: TaskResolver;
|
|
11
|
-
reject: TaskRejecter;
|
|
12
|
-
hold: TaskHolder;
|
|
13
|
-
}) => Promise<T>;
|
|
14
|
-
export declare class BrokerAPI {
|
|
15
|
-
connection: amqp.ChannelModel;
|
|
16
|
-
channels: Record<string, amqp.Channel>;
|
|
17
|
-
handlers: Record<string, TaskHandler<any>[]>;
|
|
18
|
-
private static __instance;
|
|
19
|
-
private constructor();
|
|
20
|
-
static instance(): Promise<BrokerAPI | null>;
|
|
21
|
-
private assertQueue;
|
|
22
|
-
private addToQueueWithHeaders;
|
|
23
|
-
addToQueue(queueId: string, taskId: string, options?: {
|
|
24
|
-
retries?: number;
|
|
25
|
-
maxRetries?: number;
|
|
26
|
-
}): Promise<boolean>;
|
|
27
|
-
registerQueueHandler<T>(queueId: string, handler: TaskHandler<T>): Promise<void>;
|
|
28
|
-
}
|
|
1
|
+
import * as amqp from 'amqplib';
|
|
2
|
+
export declare const Q: (...args: string[]) => string;
|
|
3
|
+
export interface RequestBody {
|
|
4
|
+
taskId: string;
|
|
5
|
+
}
|
|
6
|
+
export type TaskResolver = () => void;
|
|
7
|
+
export type TaskRejecter = () => void;
|
|
8
|
+
export type TaskHolder = () => void;
|
|
9
|
+
export type TaskHandler<T> = (taskId: string, actions: {
|
|
10
|
+
resolve: TaskResolver;
|
|
11
|
+
reject: TaskRejecter;
|
|
12
|
+
hold: TaskHolder;
|
|
13
|
+
}) => Promise<T>;
|
|
14
|
+
export declare class BrokerAPI {
|
|
15
|
+
connection: amqp.ChannelModel;
|
|
16
|
+
channels: Record<string, amqp.Channel>;
|
|
17
|
+
handlers: Record<string, TaskHandler<any>[]>;
|
|
18
|
+
private static __instance;
|
|
19
|
+
private constructor();
|
|
20
|
+
static instance(): Promise<BrokerAPI | null>;
|
|
21
|
+
private assertQueue;
|
|
22
|
+
private addToQueueWithHeaders;
|
|
23
|
+
addToQueue(queueId: string, taskId: string, options?: {
|
|
24
|
+
retries?: number;
|
|
25
|
+
maxRetries?: number;
|
|
26
|
+
}): Promise<boolean>;
|
|
27
|
+
registerQueueHandler<T>(queueId: string, handler: TaskHandler<T>): Promise<void>;
|
|
28
|
+
}
|
|
@@ -1,112 +1,112 @@
|
|
|
1
|
-
import * as amqp from 'amqplib';
|
|
2
|
-
import { ENV } from '../env.js';
|
|
3
|
-
const RABBITMQ_ENABLED = ENV.RABBITMQ_ENABLED;
|
|
4
|
-
const RABBITMQ_URL = ENV.RABBITMQ_URL;
|
|
5
|
-
if (!RABBITMQ_URL && RABBITMQ_ENABLED)
|
|
6
|
-
throw new Error('[ERROR:ENV] Missing RabbitMQ configuration.');
|
|
7
|
-
export const Q = (...args) => {
|
|
8
|
-
if (ENV.ENVIRONMENT === 'production')
|
|
9
|
-
return args.join('.');
|
|
10
|
-
else
|
|
11
|
-
return ['dev', ...args].join('.');
|
|
12
|
-
};
|
|
13
|
-
export class BrokerAPI {
|
|
14
|
-
connection;
|
|
15
|
-
channels = {};
|
|
16
|
-
handlers = {};
|
|
17
|
-
static __instance = null;
|
|
18
|
-
constructor() { }
|
|
19
|
-
static async instance() {
|
|
20
|
-
if (!RABBITMQ_ENABLED)
|
|
21
|
-
return Promise.resolve(null);
|
|
22
|
-
if (BrokerAPI.__instance)
|
|
23
|
-
return Promise.resolve(BrokerAPI.__instance);
|
|
24
|
-
const instance = new BrokerAPI();
|
|
25
|
-
instance.connection = await amqp.connect(RABBITMQ_URL);
|
|
26
|
-
instance.channels = {
|
|
27
|
-
asserter: await instance.connection.createChannel(),
|
|
28
|
-
reader: await instance.connection.createChannel(),
|
|
29
|
-
writer: await instance.connection.createChannel(),
|
|
30
|
-
};
|
|
31
|
-
BrokerAPI.__instance = instance;
|
|
32
|
-
return instance;
|
|
33
|
-
}
|
|
34
|
-
async assertQueue(queueId, options) {
|
|
35
|
-
const result = await this.channels.asserter.assertQueue(queueId, {
|
|
36
|
-
durable: true,
|
|
37
|
-
...options,
|
|
38
|
-
});
|
|
39
|
-
console.log(`[BROKER] Queue "${queueId}" has been asserted.`);
|
|
40
|
-
return result;
|
|
41
|
-
}
|
|
42
|
-
async addToQueueWithHeaders(queueId, taskId, headers, options) {
|
|
43
|
-
await this.assertQueue(queueId);
|
|
44
|
-
const bodyStr = JSON.stringify({ taskId });
|
|
45
|
-
const result = this.channels.writer.sendToQueue(queueId, Buffer.from(bodyStr), {
|
|
46
|
-
persistent: true,
|
|
47
|
-
contentType: 'application/json',
|
|
48
|
-
headers: {
|
|
49
|
-
...headers,
|
|
50
|
-
'x-retries': options?.retries ?? 0,
|
|
51
|
-
'x-max-retries': options?.maxRetries ?? 3,
|
|
52
|
-
'x-first-published': Date.now(),
|
|
53
|
-
},
|
|
54
|
-
messageId: taskId,
|
|
55
|
-
});
|
|
56
|
-
if (result) {
|
|
57
|
-
console.log(`[BROKER] Message sent to queue "${queueId}": ${bodyStr}.`);
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
console.log(`[BROKER] Message could not sent to queue "${queueId}": ${bodyStr}.`);
|
|
61
|
-
}
|
|
62
|
-
return Promise.resolve(result);
|
|
63
|
-
}
|
|
64
|
-
async addToQueue(queueId, taskId, options) {
|
|
65
|
-
await this.assertQueue(queueId);
|
|
66
|
-
return this.addToQueueWithHeaders(queueId, taskId, {}, options);
|
|
67
|
-
}
|
|
68
|
-
async registerQueueHandler(queueId, handler) {
|
|
69
|
-
await this.assertQueue(queueId);
|
|
70
|
-
if (Object.keys(this.handlers).includes(queueId)) {
|
|
71
|
-
this.handlers[queueId].push(handler);
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const brokerAPI = this;
|
|
75
|
-
this.handlers[queueId] = [handler];
|
|
76
|
-
const resolve = (message) => () => {
|
|
77
|
-
this.channels.writer.ack(message);
|
|
78
|
-
};
|
|
79
|
-
const hold = (message) => () => {
|
|
80
|
-
this.channels.writer.nack(message, false, true);
|
|
81
|
-
};
|
|
82
|
-
const reject = (queueId, message) => () => {
|
|
83
|
-
const content = message?.content?.toString?.();
|
|
84
|
-
const request = JSON.parse(content);
|
|
85
|
-
const headers = message.properties.headers ?? {};
|
|
86
|
-
const retries = headers['x-retries'] ?? 0;
|
|
87
|
-
const maxRetries = headers['x-max-retries'] ?? 3;
|
|
88
|
-
if (retries >= maxRetries) {
|
|
89
|
-
this.channels.writer.ack(message);
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
void this.addToQueueWithHeaders(queueId, request.taskId, headers, {
|
|
93
|
-
retries: retries + 1,
|
|
94
|
-
maxRetries,
|
|
95
|
-
}).then(() => this.channels.writer.ack(message));
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
await this.channels.reader.consume(queueId, (message) => {
|
|
99
|
-
const handlers = brokerAPI.handlers;
|
|
100
|
-
const content = message?.content?.toString?.();
|
|
101
|
-
const request = JSON.parse(content);
|
|
102
|
-
for (const handler of handlers[queueId]) {
|
|
103
|
-
void handler(request.taskId, {
|
|
104
|
-
resolve: resolve(message),
|
|
105
|
-
reject: reject(queueId, message),
|
|
106
|
-
hold: hold(message),
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
1
|
+
import * as amqp from 'amqplib';
|
|
2
|
+
import { ENV } from '../env.js';
|
|
3
|
+
const RABBITMQ_ENABLED = ENV.RABBITMQ_ENABLED;
|
|
4
|
+
const RABBITMQ_URL = ENV.RABBITMQ_URL;
|
|
5
|
+
if (!RABBITMQ_URL && RABBITMQ_ENABLED)
|
|
6
|
+
throw new Error('[ERROR:ENV] Missing RabbitMQ configuration.');
|
|
7
|
+
export const Q = (...args) => {
|
|
8
|
+
if (ENV.ENVIRONMENT === 'production')
|
|
9
|
+
return args.join('.');
|
|
10
|
+
else
|
|
11
|
+
return ['dev', ...args].join('.');
|
|
12
|
+
};
|
|
13
|
+
export class BrokerAPI {
|
|
14
|
+
connection;
|
|
15
|
+
channels = {};
|
|
16
|
+
handlers = {};
|
|
17
|
+
static __instance = null;
|
|
18
|
+
constructor() { }
|
|
19
|
+
static async instance() {
|
|
20
|
+
if (!RABBITMQ_ENABLED)
|
|
21
|
+
return Promise.resolve(null);
|
|
22
|
+
if (BrokerAPI.__instance)
|
|
23
|
+
return Promise.resolve(BrokerAPI.__instance);
|
|
24
|
+
const instance = new BrokerAPI();
|
|
25
|
+
instance.connection = await amqp.connect(RABBITMQ_URL);
|
|
26
|
+
instance.channels = {
|
|
27
|
+
asserter: await instance.connection.createChannel(),
|
|
28
|
+
reader: await instance.connection.createChannel(),
|
|
29
|
+
writer: await instance.connection.createChannel(),
|
|
30
|
+
};
|
|
31
|
+
BrokerAPI.__instance = instance;
|
|
32
|
+
return instance;
|
|
33
|
+
}
|
|
34
|
+
async assertQueue(queueId, options) {
|
|
35
|
+
const result = await this.channels.asserter.assertQueue(queueId, {
|
|
36
|
+
durable: true,
|
|
37
|
+
...options,
|
|
38
|
+
});
|
|
39
|
+
console.log(`[BROKER] Queue "${queueId}" has been asserted.`);
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
async addToQueueWithHeaders(queueId, taskId, headers, options) {
|
|
43
|
+
await this.assertQueue(queueId);
|
|
44
|
+
const bodyStr = JSON.stringify({ taskId });
|
|
45
|
+
const result = this.channels.writer.sendToQueue(queueId, Buffer.from(bodyStr), {
|
|
46
|
+
persistent: true,
|
|
47
|
+
contentType: 'application/json',
|
|
48
|
+
headers: {
|
|
49
|
+
...headers,
|
|
50
|
+
'x-retries': options?.retries ?? 0,
|
|
51
|
+
'x-max-retries': options?.maxRetries ?? 3,
|
|
52
|
+
'x-first-published': Date.now(),
|
|
53
|
+
},
|
|
54
|
+
messageId: taskId,
|
|
55
|
+
});
|
|
56
|
+
if (result) {
|
|
57
|
+
console.log(`[BROKER] Message sent to queue "${queueId}": ${bodyStr}.`);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
console.log(`[BROKER] Message could not sent to queue "${queueId}": ${bodyStr}.`);
|
|
61
|
+
}
|
|
62
|
+
return Promise.resolve(result);
|
|
63
|
+
}
|
|
64
|
+
async addToQueue(queueId, taskId, options) {
|
|
65
|
+
await this.assertQueue(queueId);
|
|
66
|
+
return this.addToQueueWithHeaders(queueId, taskId, {}, options);
|
|
67
|
+
}
|
|
68
|
+
async registerQueueHandler(queueId, handler) {
|
|
69
|
+
await this.assertQueue(queueId);
|
|
70
|
+
if (Object.keys(this.handlers).includes(queueId)) {
|
|
71
|
+
this.handlers[queueId].push(handler);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const brokerAPI = this;
|
|
75
|
+
this.handlers[queueId] = [handler];
|
|
76
|
+
const resolve = (message) => () => {
|
|
77
|
+
this.channels.writer.ack(message);
|
|
78
|
+
};
|
|
79
|
+
const hold = (message) => () => {
|
|
80
|
+
this.channels.writer.nack(message, false, true);
|
|
81
|
+
};
|
|
82
|
+
const reject = (queueId, message) => () => {
|
|
83
|
+
const content = message?.content?.toString?.();
|
|
84
|
+
const request = JSON.parse(content);
|
|
85
|
+
const headers = message.properties.headers ?? {};
|
|
86
|
+
const retries = headers['x-retries'] ?? 0;
|
|
87
|
+
const maxRetries = headers['x-max-retries'] ?? 3;
|
|
88
|
+
if (retries >= maxRetries) {
|
|
89
|
+
this.channels.writer.ack(message);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
void this.addToQueueWithHeaders(queueId, request.taskId, headers, {
|
|
93
|
+
retries: retries + 1,
|
|
94
|
+
maxRetries,
|
|
95
|
+
}).then(() => this.channels.writer.ack(message));
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
await this.channels.reader.consume(queueId, (message) => {
|
|
99
|
+
const handlers = brokerAPI.handlers;
|
|
100
|
+
const content = message?.content?.toString?.();
|
|
101
|
+
const request = JSON.parse(content);
|
|
102
|
+
for (const handler of handlers[queueId]) {
|
|
103
|
+
void handler(request.taskId, {
|
|
104
|
+
resolve: resolve(message),
|
|
105
|
+
reject: reject(queueId, message),
|
|
106
|
+
hold: hold(message),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
112
|
//# sourceMappingURL=broker.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './broker.js';
|
|
2
|
-
export * from './base.task.js';
|
|
1
|
+
export * from './broker.js';
|
|
2
|
+
export * from './base.task.js';
|
package/dist/lib/broker/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from './broker.js';
|
|
2
|
-
export * from './base.task.js';
|
|
1
|
+
export * from './broker.js';
|
|
2
|
+
export * from './base.task.js';
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
|
@@ -5,14 +5,14 @@ const LONG_TEXT_VALIDATOR = `${TEXT_PREPROCESS}z.string().describe("textarea"))`
|
|
|
5
5
|
const NUMBER_VALIDATOR = 'z.number()';
|
|
6
6
|
const SIGNATURE_VALIDATOR = `${TEXT_PREPROCESS}z.string().nonempty({ message: "This field is required." }))`;
|
|
7
7
|
const DROPDOWN_VALIDATOR = `z.enum(["Option 1", "Option 2"], {message:"This field is required."})`;
|
|
8
|
-
const MULTISELECT_VALIDATOR = `z.array(
|
|
9
|
-
z.enum(
|
|
10
|
-
[
|
|
11
|
-
"Option 1",
|
|
12
|
-
"Option 2"
|
|
13
|
-
],
|
|
14
|
-
{ message: "This field is required." }
|
|
15
|
-
)
|
|
8
|
+
const MULTISELECT_VALIDATOR = `z.array(
|
|
9
|
+
z.enum(
|
|
10
|
+
[
|
|
11
|
+
"Option 1",
|
|
12
|
+
"Option 2"
|
|
13
|
+
],
|
|
14
|
+
{ message: "This field is required." }
|
|
15
|
+
)
|
|
16
16
|
).describe("multiselect")`;
|
|
17
17
|
const DATE_VALIDATOR = 'z.coerce.date()';
|
|
18
18
|
const TIME_VALIDATOR = 'z.string().describe("time")';
|