@nocobase/server 1.8.0-alpha.9 → 1.8.0-beta.10
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/lib/application.d.ts +0 -5
- package/lib/application.js +0 -6
- package/lib/index.d.ts +0 -1
- package/lib/index.js +1 -3
- package/package.json +15 -15
- package/lib/event-queue.d.ts +0 -89
- package/lib/event-queue.js +0 -328
package/lib/application.d.ts
CHANGED
|
@@ -35,7 +35,6 @@ import AesEncryptor from './aes-encryptor';
|
|
|
35
35
|
import { AuditManager } from './audit-manager';
|
|
36
36
|
import { Environment } from './environment';
|
|
37
37
|
import { ServiceContainer } from './service-container';
|
|
38
|
-
import { EventQueue, EventQueueOptions } from './event-queue';
|
|
39
38
|
export type PluginType = string | typeof Plugin;
|
|
40
39
|
export type PluginConfiguration = PluginType | [PluginType, any];
|
|
41
40
|
export interface ResourceManagerOptions {
|
|
@@ -56,7 +55,6 @@ export interface AppTelemetryOptions extends TelemetryOptions {
|
|
|
56
55
|
enabled?: boolean;
|
|
57
56
|
}
|
|
58
57
|
export interface ApplicationOptions {
|
|
59
|
-
instanceId?: string;
|
|
60
58
|
database?: IDatabaseOptions | Database;
|
|
61
59
|
cacheManager?: CacheManagerOptions;
|
|
62
60
|
/**
|
|
@@ -84,7 +82,6 @@ export interface ApplicationOptions {
|
|
|
84
82
|
authManager?: AuthManagerOptions;
|
|
85
83
|
auditManager?: AuditManager;
|
|
86
84
|
lockManager?: LockManagerOptions;
|
|
87
|
-
eventQueue?: EventQueueOptions;
|
|
88
85
|
/**
|
|
89
86
|
* @internal
|
|
90
87
|
*/
|
|
@@ -131,7 +128,6 @@ export type MaintainingCommandStatus = {
|
|
|
131
128
|
};
|
|
132
129
|
export declare class Application<StateT = DefaultState, ContextT = DefaultContext> extends Koa implements AsyncEmitter {
|
|
133
130
|
options: ApplicationOptions;
|
|
134
|
-
readonly instanceId: string;
|
|
135
131
|
/**
|
|
136
132
|
* @internal
|
|
137
133
|
*/
|
|
@@ -178,7 +174,6 @@ export declare class Application<StateT = DefaultState, ContextT = DefaultContex
|
|
|
178
174
|
private _actionCommand;
|
|
179
175
|
container: ServiceContainer;
|
|
180
176
|
lockManager: LockManager;
|
|
181
|
-
eventQueue: EventQueue;
|
|
182
177
|
constructor(options: ApplicationOptions);
|
|
183
178
|
private static staticCommands;
|
|
184
179
|
static addCommand(callback: (app: Application) => void): void;
|
package/lib/application.js
CHANGED
|
@@ -56,7 +56,6 @@ var import_glob = __toESM(require("glob"));
|
|
|
56
56
|
var import_koa = __toESM(require("koa"));
|
|
57
57
|
var import_koa_compose = __toESM(require("koa-compose"));
|
|
58
58
|
var import_lodash = __toESM(require("lodash"));
|
|
59
|
-
var import_nanoid = require("nanoid");
|
|
60
59
|
var import_path = __toESM(require("path"));
|
|
61
60
|
var import_semver = __toESM(require("semver"));
|
|
62
61
|
var import_acl = require("./acl");
|
|
@@ -82,12 +81,10 @@ var import_aes_encryptor = __toESM(require("./aes-encryptor"));
|
|
|
82
81
|
var import_audit_manager = require("./audit-manager");
|
|
83
82
|
var import_environment = require("./environment");
|
|
84
83
|
var import_service_container = require("./service-container");
|
|
85
|
-
var import_event_queue = require("./event-queue");
|
|
86
84
|
const _Application = class _Application extends import_koa.default {
|
|
87
85
|
constructor(options) {
|
|
88
86
|
super();
|
|
89
87
|
this.options = options;
|
|
90
|
-
this.instanceId = options.instanceId || (0, import_nanoid.nanoid)();
|
|
91
88
|
this.context.reqId = (0, import_crypto.randomUUID)();
|
|
92
89
|
this.rawOptions = this.name == "main" ? import_lodash.default.cloneDeep(options) : {};
|
|
93
90
|
this.init();
|
|
@@ -95,7 +92,6 @@ const _Application = class _Application extends import_koa.default {
|
|
|
95
92
|
this._appSupervisor.addApp(this);
|
|
96
93
|
}
|
|
97
94
|
}
|
|
98
|
-
instanceId;
|
|
99
95
|
/**
|
|
100
96
|
* @internal
|
|
101
97
|
*/
|
|
@@ -135,7 +131,6 @@ const _Application = class _Application extends import_koa.default {
|
|
|
135
131
|
_actionCommand;
|
|
136
132
|
container = new import_service_container.ServiceContainer();
|
|
137
133
|
lockManager;
|
|
138
|
-
eventQueue;
|
|
139
134
|
static addCommand(callback) {
|
|
140
135
|
this.staticCommands.push(callback);
|
|
141
136
|
}
|
|
@@ -860,7 +855,6 @@ const _Application = class _Application extends import_koa.default {
|
|
|
860
855
|
this._i18n = (0, import_helper.createI18n)(options);
|
|
861
856
|
this.pubSubManager = (0, import_pub_sub_manager.createPubSubManager)(this, options.pubSubManager);
|
|
862
857
|
this.syncMessageManager = new import_sync_message_manager.SyncMessageManager(this, options.syncMessageManager);
|
|
863
|
-
this.eventQueue = new import_event_queue.EventQueue(this, options.eventQueue);
|
|
864
858
|
this.lockManager = new import_lock_manager.LockManager({
|
|
865
859
|
defaultAdapter: process.env.LOCK_ADAPTER_DEFAULT,
|
|
866
860
|
...options.lockManager
|
package/lib/index.d.ts
CHANGED
|
@@ -17,7 +17,6 @@ export * from './migration';
|
|
|
17
17
|
export * from './plugin';
|
|
18
18
|
export * from './plugin-manager';
|
|
19
19
|
export * from './pub-sub-manager';
|
|
20
|
-
export * from './event-queue';
|
|
21
20
|
export declare const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
|
|
22
21
|
export { appendToBuiltInPlugins, findAllPlugins, findBuiltInPlugins, findLocalPlugins, packageNameTrim, } from './plugin-manager/findPackageNames';
|
|
23
22
|
export { runPluginStaticImports } from './run-plugin-static-imports';
|
package/lib/index.js
CHANGED
|
@@ -59,7 +59,6 @@ __reExport(src_exports, require("./migration"), module.exports);
|
|
|
59
59
|
__reExport(src_exports, require("./plugin"), module.exports);
|
|
60
60
|
__reExport(src_exports, require("./plugin-manager"), module.exports);
|
|
61
61
|
__reExport(src_exports, require("./pub-sub-manager"), module.exports);
|
|
62
|
-
__reExport(src_exports, require("./event-queue"), module.exports);
|
|
63
62
|
var import_findPackageNames = require("./plugin-manager/findPackageNames");
|
|
64
63
|
var import_run_plugin_static_imports = require("./run-plugin-static-imports");
|
|
65
64
|
const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
|
|
@@ -81,6 +80,5 @@ const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
|
|
|
81
80
|
...require("./migration"),
|
|
82
81
|
...require("./plugin"),
|
|
83
82
|
...require("./plugin-manager"),
|
|
84
|
-
...require("./pub-sub-manager")
|
|
85
|
-
...require("./event-queue")
|
|
83
|
+
...require("./pub-sub-manager")
|
|
86
84
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/server",
|
|
3
|
-
"version": "1.8.0-
|
|
3
|
+
"version": "1.8.0-beta.10",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "./lib/index.d.ts",
|
|
6
6
|
"license": "AGPL-3.0",
|
|
@@ -10,19 +10,19 @@
|
|
|
10
10
|
"@koa/cors": "^5.0.0",
|
|
11
11
|
"@koa/multer": "^3.1.0",
|
|
12
12
|
"@koa/router": "^13.1.0",
|
|
13
|
-
"@nocobase/acl": "1.8.0-
|
|
14
|
-
"@nocobase/actions": "1.8.0-
|
|
15
|
-
"@nocobase/auth": "1.8.0-
|
|
16
|
-
"@nocobase/cache": "1.8.0-
|
|
17
|
-
"@nocobase/data-source-manager": "1.8.0-
|
|
18
|
-
"@nocobase/database": "1.8.0-
|
|
19
|
-
"@nocobase/evaluators": "1.8.0-
|
|
20
|
-
"@nocobase/lock-manager": "1.8.0-
|
|
21
|
-
"@nocobase/logger": "1.8.0-
|
|
22
|
-
"@nocobase/resourcer": "1.8.0-
|
|
23
|
-
"@nocobase/sdk": "1.8.0-
|
|
24
|
-
"@nocobase/telemetry": "1.8.0-
|
|
25
|
-
"@nocobase/utils": "1.8.0-
|
|
13
|
+
"@nocobase/acl": "1.8.0-beta.10",
|
|
14
|
+
"@nocobase/actions": "1.8.0-beta.10",
|
|
15
|
+
"@nocobase/auth": "1.8.0-beta.10",
|
|
16
|
+
"@nocobase/cache": "1.8.0-beta.10",
|
|
17
|
+
"@nocobase/data-source-manager": "1.8.0-beta.10",
|
|
18
|
+
"@nocobase/database": "1.8.0-beta.10",
|
|
19
|
+
"@nocobase/evaluators": "1.8.0-beta.10",
|
|
20
|
+
"@nocobase/lock-manager": "1.8.0-beta.10",
|
|
21
|
+
"@nocobase/logger": "1.8.0-beta.10",
|
|
22
|
+
"@nocobase/resourcer": "1.8.0-beta.10",
|
|
23
|
+
"@nocobase/sdk": "1.8.0-beta.10",
|
|
24
|
+
"@nocobase/telemetry": "1.8.0-beta.10",
|
|
25
|
+
"@nocobase/utils": "1.8.0-beta.10",
|
|
26
26
|
"@types/decompress": "4.2.7",
|
|
27
27
|
"@types/ini": "^1.3.31",
|
|
28
28
|
"@types/koa-send": "^4.1.3",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"@types/serve-handler": "^6.1.1",
|
|
58
58
|
"@types/ws": "^8.5.5"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "09fe854edfc44f45422fa983093dd34694416c5a"
|
|
61
61
|
}
|
package/lib/event-queue.d.ts
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is part of the NocoBase (R) project.
|
|
3
|
-
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
-
* Authors: NocoBase Team.
|
|
5
|
-
*
|
|
6
|
-
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
-
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
-
*/
|
|
9
|
-
import Application from './application';
|
|
10
|
-
export type QueueCallbackOptions = {
|
|
11
|
-
id?: string;
|
|
12
|
-
retried?: number;
|
|
13
|
-
signal?: AbortSignal;
|
|
14
|
-
};
|
|
15
|
-
export type QueueCallback = (message: any, options: QueueCallbackOptions) => Promise<void> | void;
|
|
16
|
-
export type QueueEventOptions = {
|
|
17
|
-
interval?: number;
|
|
18
|
-
concurrency?: number;
|
|
19
|
-
idle(): boolean;
|
|
20
|
-
process: QueueCallback;
|
|
21
|
-
};
|
|
22
|
-
export type QueueMessageOptions = {
|
|
23
|
-
timeout?: number;
|
|
24
|
-
maxRetries?: number;
|
|
25
|
-
retried?: number;
|
|
26
|
-
timestamp?: number;
|
|
27
|
-
};
|
|
28
|
-
export interface IEventQueueAdapter {
|
|
29
|
-
isConnected(): boolean;
|
|
30
|
-
connect(): Promise<void> | void;
|
|
31
|
-
close(): Promise<void> | void;
|
|
32
|
-
subscribe(channel: string, event: QueueEventOptions): void;
|
|
33
|
-
unsubscribe(channel: string): void;
|
|
34
|
-
publish(channel: string, message: any, options: QueueMessageOptions): Promise<void> | void;
|
|
35
|
-
}
|
|
36
|
-
export interface EventQueueOptions {
|
|
37
|
-
channelPrefix?: string;
|
|
38
|
-
}
|
|
39
|
-
export declare const QUEUE_DEFAULT_INTERVAL = 1000;
|
|
40
|
-
export declare const QUEUE_DEFAULT_CONCURRENCY = 1;
|
|
41
|
-
export declare const QUEUE_DEFAULT_ACK_TIMEOUT = 15000;
|
|
42
|
-
export declare class MemoryEventQueueAdapter implements IEventQueueAdapter {
|
|
43
|
-
private options;
|
|
44
|
-
private connected;
|
|
45
|
-
private emitter;
|
|
46
|
-
private reading;
|
|
47
|
-
private events;
|
|
48
|
-
protected queues: Map<string, {
|
|
49
|
-
id: string;
|
|
50
|
-
content: any;
|
|
51
|
-
options?: QueueMessageOptions;
|
|
52
|
-
}[]>;
|
|
53
|
-
get processing(): Promise<void[]>;
|
|
54
|
-
get storagePath(): string;
|
|
55
|
-
listen: (channel: string) => Promise<void>;
|
|
56
|
-
constructor(options: {
|
|
57
|
-
appName: string;
|
|
58
|
-
});
|
|
59
|
-
isConnected(): boolean;
|
|
60
|
-
private loadFromStorage;
|
|
61
|
-
private saveToStorage;
|
|
62
|
-
connect(): Promise<void>;
|
|
63
|
-
close(): Promise<void>;
|
|
64
|
-
subscribe(channel: string, options: QueueEventOptions): void;
|
|
65
|
-
unsubscribe(channel: string): void;
|
|
66
|
-
publish(channel: string, content: any, options?: QueueMessageOptions): void;
|
|
67
|
-
read(channel: string): Promise<void>;
|
|
68
|
-
process(channel: any, { id, message }: {
|
|
69
|
-
id: any;
|
|
70
|
-
message: any;
|
|
71
|
-
}): Promise<void>;
|
|
72
|
-
}
|
|
73
|
-
export declare class EventQueue {
|
|
74
|
-
protected app: Application;
|
|
75
|
-
protected options: EventQueueOptions;
|
|
76
|
-
protected adapter: IEventQueueAdapter;
|
|
77
|
-
protected events: Map<string, QueueEventOptions>;
|
|
78
|
-
get channelPrefix(): string;
|
|
79
|
-
constructor(app: Application, options?: EventQueueOptions);
|
|
80
|
-
getFullChannel(channel: string): string;
|
|
81
|
-
setAdapter<A extends IEventQueueAdapter>(adapter: A): void;
|
|
82
|
-
isConnected(): boolean;
|
|
83
|
-
connect(): Promise<void>;
|
|
84
|
-
close(): Promise<void>;
|
|
85
|
-
subscribe(channel: string, options: QueueEventOptions): void;
|
|
86
|
-
unsubscribe(channel: string): void;
|
|
87
|
-
publish(channel: string, message: any, options?: QueueMessageOptions): Promise<void>;
|
|
88
|
-
}
|
|
89
|
-
export default EventQueue;
|
package/lib/event-queue.js
DELETED
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is part of the NocoBase (R) project.
|
|
3
|
-
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
-
* Authors: NocoBase Team.
|
|
5
|
-
*
|
|
6
|
-
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
-
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
var __create = Object.create;
|
|
11
|
-
var __defProp = Object.defineProperty;
|
|
12
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
13
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
15
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
16
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
17
|
-
var __export = (target, all) => {
|
|
18
|
-
for (var name in all)
|
|
19
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
20
|
-
};
|
|
21
|
-
var __copyProps = (to, from, except, desc) => {
|
|
22
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
23
|
-
for (let key of __getOwnPropNames(from))
|
|
24
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
25
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
26
|
-
}
|
|
27
|
-
return to;
|
|
28
|
-
};
|
|
29
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
30
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
31
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
32
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
33
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
34
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
35
|
-
mod
|
|
36
|
-
));
|
|
37
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
38
|
-
var event_queue_exports = {};
|
|
39
|
-
__export(event_queue_exports, {
|
|
40
|
-
EventQueue: () => EventQueue,
|
|
41
|
-
MemoryEventQueueAdapter: () => MemoryEventQueueAdapter,
|
|
42
|
-
QUEUE_DEFAULT_ACK_TIMEOUT: () => QUEUE_DEFAULT_ACK_TIMEOUT,
|
|
43
|
-
QUEUE_DEFAULT_CONCURRENCY: () => QUEUE_DEFAULT_CONCURRENCY,
|
|
44
|
-
QUEUE_DEFAULT_INTERVAL: () => QUEUE_DEFAULT_INTERVAL,
|
|
45
|
-
default: () => event_queue_default
|
|
46
|
-
});
|
|
47
|
-
module.exports = __toCommonJS(event_queue_exports);
|
|
48
|
-
var import_crypto = require("crypto");
|
|
49
|
-
var import_events = require("events");
|
|
50
|
-
var import_path = __toESM(require("path"));
|
|
51
|
-
var import_promises = __toESM(require("fs/promises"));
|
|
52
|
-
const QUEUE_DEFAULT_INTERVAL = 1e3;
|
|
53
|
-
const QUEUE_DEFAULT_CONCURRENCY = 1;
|
|
54
|
-
const QUEUE_DEFAULT_ACK_TIMEOUT = 15e3;
|
|
55
|
-
const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
56
|
-
constructor(options) {
|
|
57
|
-
this.options = options;
|
|
58
|
-
this.emitter.setMaxListeners(0);
|
|
59
|
-
}
|
|
60
|
-
connected = false;
|
|
61
|
-
emitter = new import_events.EventEmitter();
|
|
62
|
-
reading = /* @__PURE__ */ new Map();
|
|
63
|
-
events = /* @__PURE__ */ new Map();
|
|
64
|
-
queues = /* @__PURE__ */ new Map();
|
|
65
|
-
get processing() {
|
|
66
|
-
const processing = Array.from(this.reading.values());
|
|
67
|
-
if (processing.length > 0) {
|
|
68
|
-
return Promise.all(processing);
|
|
69
|
-
}
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
get storagePath() {
|
|
73
|
-
return import_path.default.resolve(process.cwd(), "storage", "apps", this.options.appName, "event-queue.json");
|
|
74
|
-
}
|
|
75
|
-
listen = /* @__PURE__ */ __name(async (channel) => {
|
|
76
|
-
if (!this.connected) {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
if (this.reading.has(channel)) {
|
|
80
|
-
console.debug(`memory queue (${channel}) is already reading, waiting last reading to end...`);
|
|
81
|
-
await this.reading.get(channel);
|
|
82
|
-
}
|
|
83
|
-
const event = this.events.get(channel);
|
|
84
|
-
if (!event) {
|
|
85
|
-
console.warn(`memory queue (${channel}) not found, skipping...`);
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
if (!event.idle()) {
|
|
89
|
-
console.debug(`memory queue (${channel}) is not idle, skipping...`);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
const reading = this.read(channel);
|
|
93
|
-
this.reading.set(channel, reading);
|
|
94
|
-
await reading;
|
|
95
|
-
}, "listen");
|
|
96
|
-
isConnected() {
|
|
97
|
-
return this.connected;
|
|
98
|
-
}
|
|
99
|
-
async loadFromStorage() {
|
|
100
|
-
let queues = {};
|
|
101
|
-
let exists = false;
|
|
102
|
-
try {
|
|
103
|
-
await import_promises.default.stat(this.storagePath);
|
|
104
|
-
exists = true;
|
|
105
|
-
} catch (ex) {
|
|
106
|
-
console.info(`memory queue storage file not found, skip`);
|
|
107
|
-
}
|
|
108
|
-
if (exists) {
|
|
109
|
-
try {
|
|
110
|
-
const queueJson = await import_promises.default.readFile(this.storagePath);
|
|
111
|
-
queues = JSON.parse(queueJson.toString());
|
|
112
|
-
console.debug("memory queue loaded from storage", queues);
|
|
113
|
-
await import_promises.default.unlink(this.storagePath);
|
|
114
|
-
} catch (ex) {
|
|
115
|
-
console.error("failed to load queue from storage", ex);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
this.queues = new Map(Object.entries(queues));
|
|
119
|
-
}
|
|
120
|
-
async saveToStorage() {
|
|
121
|
-
const queues = Array.from(this.queues.entries()).reduce((acc, [channel, queue]) => {
|
|
122
|
-
if (queue == null ? void 0 : queue.length) {
|
|
123
|
-
acc[channel] = queue;
|
|
124
|
-
}
|
|
125
|
-
return acc;
|
|
126
|
-
}, {});
|
|
127
|
-
if (Object.keys(queues).length) {
|
|
128
|
-
await import_promises.default.mkdir(import_path.default.dirname(this.storagePath), { recursive: true });
|
|
129
|
-
await import_promises.default.writeFile(this.storagePath, JSON.stringify(queues));
|
|
130
|
-
console.debug("memory queue saved to storage", queues);
|
|
131
|
-
} else {
|
|
132
|
-
console.debug("memory queue empty, no need to save to storage");
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
async connect() {
|
|
136
|
-
if (this.connected) {
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
await this.loadFromStorage();
|
|
140
|
-
this.connected = true;
|
|
141
|
-
setImmediate(() => {
|
|
142
|
-
for (const channel of this.queues.keys()) {
|
|
143
|
-
const queue = this.queues.get(channel);
|
|
144
|
-
if (!(queue == null ? void 0 : queue.length)) {
|
|
145
|
-
continue;
|
|
146
|
-
}
|
|
147
|
-
this.emitter.emit(channel, channel);
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
async close() {
|
|
152
|
-
this.connected = false;
|
|
153
|
-
if (this.processing) {
|
|
154
|
-
console.info("memory queue waiting for processing job...");
|
|
155
|
-
await this.processing;
|
|
156
|
-
console.info("memory queue job cleaned");
|
|
157
|
-
}
|
|
158
|
-
console.log("memory queue gracefully shutting down...");
|
|
159
|
-
await this.saveToStorage();
|
|
160
|
-
}
|
|
161
|
-
subscribe(channel, options) {
|
|
162
|
-
if (this.events.has(channel)) {
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
this.events.set(channel, options);
|
|
166
|
-
if (!this.queues.has(channel)) {
|
|
167
|
-
this.queues.set(channel, []);
|
|
168
|
-
}
|
|
169
|
-
this.emitter.on(channel, this.listen);
|
|
170
|
-
}
|
|
171
|
-
unsubscribe(channel) {
|
|
172
|
-
if (!this.events.has(channel)) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
this.events.delete(channel);
|
|
176
|
-
}
|
|
177
|
-
publish(channel, content, options = { timestamp: Date.now() }) {
|
|
178
|
-
const event = this.events.get(channel);
|
|
179
|
-
if (!event) {
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
if (!this.queues.get(channel)) {
|
|
183
|
-
this.queues.set(channel, []);
|
|
184
|
-
}
|
|
185
|
-
const queue = this.queues.get(channel);
|
|
186
|
-
queue.push({ id: (0, import_crypto.randomUUID)(), content, options });
|
|
187
|
-
console.debug(`memory queue (${channel}) published message`, content);
|
|
188
|
-
setImmediate(() => {
|
|
189
|
-
this.emitter.emit(channel, channel);
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
async read(channel) {
|
|
193
|
-
const event = this.events.get(channel);
|
|
194
|
-
if (!event) {
|
|
195
|
-
this.reading.delete(channel);
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
const queue = this.queues.get(channel);
|
|
199
|
-
while (queue == null ? void 0 : queue.length) {
|
|
200
|
-
const messages = queue.slice(0, event.concurrency || QUEUE_DEFAULT_CONCURRENCY);
|
|
201
|
-
console.debug(`memory queue (${channel}) read ${messages.length} messages`, messages);
|
|
202
|
-
queue.splice(0, messages.length);
|
|
203
|
-
const batch = messages.map(({ id, ...message }) => this.process(channel, { id, message }));
|
|
204
|
-
await Promise.all(batch);
|
|
205
|
-
}
|
|
206
|
-
this.reading.delete(channel);
|
|
207
|
-
}
|
|
208
|
-
async process(channel, { id, message }) {
|
|
209
|
-
const event = this.events.get(channel);
|
|
210
|
-
const { content, options: { timeout = QUEUE_DEFAULT_ACK_TIMEOUT, maxRetries = 0, retried = 0 } = {} } = message;
|
|
211
|
-
try {
|
|
212
|
-
console.debug(`memory queue (${channel}) processing message (${id})...`, content);
|
|
213
|
-
await event.process(content, {
|
|
214
|
-
id,
|
|
215
|
-
retried,
|
|
216
|
-
signal: AbortSignal.timeout(timeout)
|
|
217
|
-
});
|
|
218
|
-
console.debug(`memory queue (${channel}) consumed message (${id})`);
|
|
219
|
-
} catch (ex) {
|
|
220
|
-
if (maxRetries > 0 && retried < maxRetries) {
|
|
221
|
-
const currentRetry = retried + 1;
|
|
222
|
-
console.warn(
|
|
223
|
-
`memory queue (${channel}) consum message (${id}) failed, retrying (${currentRetry} / ${maxRetries})...`,
|
|
224
|
-
ex
|
|
225
|
-
);
|
|
226
|
-
setImmediate(() => {
|
|
227
|
-
this.publish(channel, content, { timeout, maxRetries, retried: currentRetry, timestamp: Date.now() });
|
|
228
|
-
});
|
|
229
|
-
} else {
|
|
230
|
-
console.error(ex);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
__name(_MemoryEventQueueAdapter, "MemoryEventQueueAdapter");
|
|
236
|
-
let MemoryEventQueueAdapter = _MemoryEventQueueAdapter;
|
|
237
|
-
const _EventQueue = class _EventQueue {
|
|
238
|
-
constructor(app, options = {}) {
|
|
239
|
-
this.app = app;
|
|
240
|
-
this.options = options;
|
|
241
|
-
this.events = /* @__PURE__ */ new Map();
|
|
242
|
-
this.setAdapter(new MemoryEventQueueAdapter({ appName: this.app.name }));
|
|
243
|
-
app.on("afterStart", async () => {
|
|
244
|
-
await this.connect();
|
|
245
|
-
});
|
|
246
|
-
app.on("beforeStop", async () => {
|
|
247
|
-
app.logger.info("[queue] gracefully shuting down...");
|
|
248
|
-
await this.close();
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
adapter;
|
|
252
|
-
events = /* @__PURE__ */ new Map();
|
|
253
|
-
get channelPrefix() {
|
|
254
|
-
var _a;
|
|
255
|
-
return (_a = this.options) == null ? void 0 : _a.channelPrefix;
|
|
256
|
-
}
|
|
257
|
-
getFullChannel(channel) {
|
|
258
|
-
return [this.app.name, this.channelPrefix, channel].filter(Boolean).join(".");
|
|
259
|
-
}
|
|
260
|
-
setAdapter(adapter) {
|
|
261
|
-
this.adapter = adapter;
|
|
262
|
-
}
|
|
263
|
-
isConnected() {
|
|
264
|
-
if (!this.adapter) {
|
|
265
|
-
return false;
|
|
266
|
-
}
|
|
267
|
-
return this.adapter.isConnected();
|
|
268
|
-
}
|
|
269
|
-
async connect() {
|
|
270
|
-
if (!this.adapter) {
|
|
271
|
-
throw new Error("no adapter set, cannot connect");
|
|
272
|
-
}
|
|
273
|
-
await this.adapter.connect();
|
|
274
|
-
for (const [channel, event] of this.events.entries()) {
|
|
275
|
-
this.adapter.subscribe(this.getFullChannel(channel), event);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
async close() {
|
|
279
|
-
if (!this.adapter) {
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
await this.adapter.close();
|
|
283
|
-
for (const channel of this.events.keys()) {
|
|
284
|
-
this.adapter.unsubscribe(this.getFullChannel(channel));
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
subscribe(channel, options) {
|
|
288
|
-
if (this.events.has(channel)) {
|
|
289
|
-
this.app.logger.warn(`event queue already subscribed on channel "${channel}", new subscription will be ignored`);
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
this.events.set(channel, options);
|
|
293
|
-
if (this.isConnected()) {
|
|
294
|
-
this.adapter.subscribe(this.getFullChannel(channel), options);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
unsubscribe(channel) {
|
|
298
|
-
if (!this.events.has(channel)) {
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
this.events.delete(channel);
|
|
302
|
-
if (this.isConnected()) {
|
|
303
|
-
this.adapter.unsubscribe(this.getFullChannel(channel));
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
async publish(channel, message, options = {}) {
|
|
307
|
-
if (!this.adapter) {
|
|
308
|
-
throw new Error("no adapter set, cannot publish");
|
|
309
|
-
}
|
|
310
|
-
if (!this.isConnected()) {
|
|
311
|
-
throw new Error("event queue not connected, cannot publish");
|
|
312
|
-
}
|
|
313
|
-
const c = this.getFullChannel(channel);
|
|
314
|
-
this.app.logger.debug("event queue publishing:", { channel: c, message });
|
|
315
|
-
await this.adapter.publish(c, message, { timeout: QUEUE_DEFAULT_ACK_TIMEOUT, ...options, timestamp: Date.now() });
|
|
316
|
-
}
|
|
317
|
-
};
|
|
318
|
-
__name(_EventQueue, "EventQueue");
|
|
319
|
-
let EventQueue = _EventQueue;
|
|
320
|
-
var event_queue_default = EventQueue;
|
|
321
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
322
|
-
0 && (module.exports = {
|
|
323
|
-
EventQueue,
|
|
324
|
-
MemoryEventQueueAdapter,
|
|
325
|
-
QUEUE_DEFAULT_ACK_TIMEOUT,
|
|
326
|
-
QUEUE_DEFAULT_CONCURRENCY,
|
|
327
|
-
QUEUE_DEFAULT_INTERVAL
|
|
328
|
-
});
|