nmtjs 0.15.3 → 0.16.0-beta.2
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/dist/index.d.ts +6 -6
- package/dist/runtime/index.d.ts +2 -2
- package/dist/runtime/index.js +2 -2
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/injectables.d.ts +7 -7
- package/dist/runtime/injectables.js +6 -6
- package/dist/runtime/injectables.js.map +1 -1
- package/dist/runtime/server/config.d.ts +4 -4
- package/dist/runtime/server/config.js +2 -2
- package/dist/runtime/server/config.js.map +1 -1
- package/dist/runtime/{pubsub → subscription}/manager.d.ts +15 -14
- package/dist/runtime/{pubsub → subscription}/manager.js +59 -8
- package/dist/runtime/subscription/manager.js.map +1 -0
- package/dist/runtime/{pubsub → subscription}/redis.d.ts +7 -5
- package/dist/runtime/{pubsub → subscription}/redis.js +37 -14
- package/dist/runtime/subscription/redis.js.map +1 -0
- package/dist/runtime/workers/base.d.ts +2 -2
- package/dist/runtime/workers/base.js +5 -5
- package/dist/runtime/workers/base.js.map +1 -1
- package/package.json +11 -11
- package/src/runtime/index.ts +2 -2
- package/src/runtime/injectables.ts +16 -18
- package/src/runtime/server/config.ts +5 -5
- package/src/runtime/{pubsub → subscription}/manager.ts +118 -26
- package/src/runtime/subscription/redis.ts +157 -0
- package/src/runtime/workers/base.ts +7 -7
- package/dist/runtime/pubsub/manager.js.map +0 -1
- package/dist/runtime/pubsub/redis.js.map +0 -1
- package/src/runtime/pubsub/redis.ts +0 -106
package/dist/index.d.ts
CHANGED
|
@@ -27,9 +27,9 @@ export declare namespace neemata {
|
|
|
27
27
|
rpcStreamAbortSignal: import("@nmtjs/core").DependencyOptional<import("@nmtjs/core").LazyInjectable<AbortSignal, import("@nmtjs/core").Scope.Call>>;
|
|
28
28
|
}, import("@nmtjs/core").Scope.Global, AbortSignal>;
|
|
29
29
|
createBlob: import("@nmtjs/core").LazyInjectable<(source: string | ArrayBuffer | Blob | File | import("stream").Readable | ReadableStream<any> | Uint8Array<ArrayBufferLike>, metadata?: import("@nmtjs/protocol").ProtocolBlobMetadata | undefined) => import("@nmtjs/protocol").ProtocolBlobInterface, import("@nmtjs/core").Scope.Call>;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
subscriptionAdapter: import("@nmtjs/core").LazyInjectable<import("./runtime/index.ts").SubscriptionAdapterType, import("@nmtjs/core").Scope.Global>;
|
|
31
|
+
publish: import("@nmtjs/core").LazyInjectable<import("./runtime/index.ts").PublishFn, import("@nmtjs/core").Scope.Global>;
|
|
32
|
+
subscribe: import("@nmtjs/core").LazyInjectable<import("./runtime/index.ts").SubscribeFn, import("@nmtjs/core").Scope.Global>;
|
|
33
33
|
jobManager: import("@nmtjs/core").LazyInjectable<import("./runtime/index.ts").JobManagerInstance, import("@nmtjs/core").Scope.Global>;
|
|
34
34
|
storeConfig: import("@nmtjs/core").LazyInjectable<import("./runtime/index.ts").ServerStoreConfig, import("@nmtjs/core").Scope.Global>;
|
|
35
35
|
workerType: import("@nmtjs/core").LazyInjectable<import("./runtime/enums.ts").WorkerType, import("@nmtjs/core").Scope.Global>;
|
|
@@ -61,9 +61,9 @@ export declare namespace neemata {
|
|
|
61
61
|
rpcStreamAbortSignal: import("@nmtjs/core").DependencyOptional<import("@nmtjs/core").LazyInjectable<AbortSignal, import("@nmtjs/core").Scope.Call>>;
|
|
62
62
|
}, import("@nmtjs/core").Scope.Global, AbortSignal>;
|
|
63
63
|
createBlob: import("@nmtjs/core").LazyInjectable<(source: string | ArrayBuffer | Blob | File | import("stream").Readable | ReadableStream<any> | Uint8Array<ArrayBufferLike>, metadata?: import("@nmtjs/protocol").ProtocolBlobMetadata | undefined) => import("@nmtjs/protocol").ProtocolBlobInterface, import("@nmtjs/core").Scope.Call>;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
subscriptionAdapter: import("@nmtjs/core").LazyInjectable<import("./runtime/index.ts").SubscriptionAdapterType, import("@nmtjs/core").Scope.Global>;
|
|
65
|
+
publish: import("@nmtjs/core").LazyInjectable<import("./runtime/index.ts").PublishFn, import("@nmtjs/core").Scope.Global>;
|
|
66
|
+
subscribe: import("@nmtjs/core").LazyInjectable<import("./runtime/index.ts").SubscribeFn, import("@nmtjs/core").Scope.Global>;
|
|
67
67
|
jobManager: import("@nmtjs/core").LazyInjectable<import("./runtime/index.ts").JobManagerInstance, import("@nmtjs/core").Scope.Global>;
|
|
68
68
|
storeConfig: import("@nmtjs/core").LazyInjectable<import("./runtime/index.ts").ServerStoreConfig, import("@nmtjs/core").Scope.Global>;
|
|
69
69
|
workerType: import("@nmtjs/core").LazyInjectable<import("./runtime/enums.ts").WorkerType, import("@nmtjs/core").Scope.Global>;
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -9,8 +9,6 @@ export * from './jobs/router.ts';
|
|
|
9
9
|
export * from './jobs/step.ts';
|
|
10
10
|
export * from './jobs/types.ts';
|
|
11
11
|
export * from './plugin.ts';
|
|
12
|
-
export * from './pubsub/manager.ts';
|
|
13
|
-
export * from './pubsub/redis.ts';
|
|
14
12
|
export * from './runtime.ts';
|
|
15
13
|
export * from './scheduler/index.ts';
|
|
16
14
|
export * from './server/config.ts';
|
|
@@ -24,6 +22,8 @@ export * from './server/server.ts';
|
|
|
24
22
|
export * from './server/types.ts';
|
|
25
23
|
export * from './server/worker-pool.ts';
|
|
26
24
|
export * from './store/index.ts';
|
|
25
|
+
export * from './subscription/manager.ts';
|
|
26
|
+
export * from './subscription/redis.ts';
|
|
27
27
|
export * from './types.ts';
|
|
28
28
|
export * from './workers/application.ts';
|
|
29
29
|
export * from './workers/base.ts';
|
package/dist/runtime/index.js
CHANGED
|
@@ -9,8 +9,6 @@ export * from './jobs/router.js';
|
|
|
9
9
|
export * from './jobs/step.js';
|
|
10
10
|
export * from './jobs/types.js';
|
|
11
11
|
export * from './plugin.js';
|
|
12
|
-
export * from './pubsub/manager.js';
|
|
13
|
-
export * from './pubsub/redis.js';
|
|
14
12
|
export * from './runtime.js';
|
|
15
13
|
export * from './scheduler/index.js';
|
|
16
14
|
export * from './server/config.js';
|
|
@@ -24,6 +22,8 @@ export * from './server/server.js';
|
|
|
24
22
|
export * from './server/types.js';
|
|
25
23
|
export * from './server/worker-pool.js';
|
|
26
24
|
export * from './store/index.js';
|
|
25
|
+
export * from './subscription/manager.js';
|
|
26
|
+
export * from './subscription/redis.js';
|
|
27
27
|
export * from './types.js';
|
|
28
28
|
export * from './workers/application.js';
|
|
29
29
|
export * from './workers/base.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA;AACtC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,kBAAkB,CAAA;AAChC,cAAc,eAAe,CAAA;AAC7B,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA;AACtC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,kBAAkB,CAAA;AAChC,cAAc,eAAe,CAAA;AAC7B,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,0BAA0B,CAAA;AACxC,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kBAAkB,CAAA;AAChC,cAAc,2BAA2B,CAAA;AACzC,cAAc,yBAAyB,CAAA;AACvC,cAAc,YAAY,CAAA;AAC1B,cAAc,0BAA0B,CAAA;AACxC,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA"}
|
|
@@ -2,11 +2,11 @@ import { Scope } from '@nmtjs/core';
|
|
|
2
2
|
import type { JobWorkerPool, WorkerType } from './enums.ts';
|
|
3
3
|
import type { JobManagerInstance } from './jobs/manager.ts';
|
|
4
4
|
import type { JobExecutionContext, SaveJobProgress } from './jobs/types.ts';
|
|
5
|
-
import type { PubSubAdapterType, PubSubPublish, PubSubSubscribe } from './pubsub/manager.ts';
|
|
6
5
|
import type { ServerStoreConfig } from './server/config.ts';
|
|
7
|
-
|
|
8
|
-
export declare const
|
|
9
|
-
export declare const
|
|
6
|
+
import type { PublishFn, SubscribeFn, SubscriptionAdapterType } from './subscription/manager.ts';
|
|
7
|
+
export declare const subscriptionAdapter: import("@nmtjs/core").LazyInjectable<SubscriptionAdapterType, Scope.Global>;
|
|
8
|
+
export declare const publish: import("@nmtjs/core").LazyInjectable<PublishFn, Scope.Global>;
|
|
9
|
+
export declare const subscribe: import("@nmtjs/core").LazyInjectable<SubscribeFn, Scope.Global>;
|
|
10
10
|
export declare const jobManager: import("@nmtjs/core").LazyInjectable<JobManagerInstance, Scope.Global>;
|
|
11
11
|
export declare const storeConfig: import("@nmtjs/core").LazyInjectable<ServerStoreConfig, Scope.Global>;
|
|
12
12
|
export declare const workerType: import("@nmtjs/core").LazyInjectable<WorkerType, Scope.Global>;
|
|
@@ -15,9 +15,9 @@ export declare const jobAbortSignal: import("@nmtjs/core").LazyInjectable<AbortS
|
|
|
15
15
|
export declare const saveJobProgress: import("@nmtjs/core").LazyInjectable<SaveJobProgress, Scope.Global>;
|
|
16
16
|
export declare const currentJobInfo: import("@nmtjs/core").LazyInjectable<JobExecutionContext, Scope.Global>;
|
|
17
17
|
export declare const RuntimeInjectables: {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
subscriptionAdapter: import("@nmtjs/core").LazyInjectable<SubscriptionAdapterType, Scope.Global>;
|
|
19
|
+
publish: import("@nmtjs/core").LazyInjectable<PublishFn, Scope.Global>;
|
|
20
|
+
subscribe: import("@nmtjs/core").LazyInjectable<SubscribeFn, Scope.Global>;
|
|
21
21
|
jobManager: import("@nmtjs/core").LazyInjectable<JobManagerInstance, Scope.Global>;
|
|
22
22
|
storeConfig: import("@nmtjs/core").LazyInjectable<ServerStoreConfig, Scope.Global>;
|
|
23
23
|
workerType: import("@nmtjs/core").LazyInjectable<WorkerType, Scope.Global>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createLazyInjectable, Scope } from '@nmtjs/core';
|
|
2
|
-
export const
|
|
3
|
-
export const
|
|
4
|
-
export const
|
|
2
|
+
export const subscriptionAdapter = createLazyInjectable(Scope.Global, 'SubscriptionAdapter');
|
|
3
|
+
export const publish = createLazyInjectable(Scope.Global, 'Publish');
|
|
4
|
+
export const subscribe = createLazyInjectable(Scope.Global, 'Subscribe');
|
|
5
5
|
export const jobManager = createLazyInjectable(Scope.Global, 'JobManager');
|
|
6
6
|
export const storeConfig = createLazyInjectable(Scope.Global, 'StoreConfig');
|
|
7
7
|
export const workerType = createLazyInjectable(Scope.Global, 'WorkerType');
|
|
@@ -10,9 +10,9 @@ export const jobAbortSignal = createLazyInjectable(Scope.Global, 'JobAbortSignal
|
|
|
10
10
|
export const saveJobProgress = createLazyInjectable(Scope.Global, 'SaveJobProgress');
|
|
11
11
|
export const currentJobInfo = createLazyInjectable(Scope.Global, 'CurrentJobInfo');
|
|
12
12
|
export const RuntimeInjectables = {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
subscriptionAdapter,
|
|
14
|
+
publish,
|
|
15
|
+
subscribe,
|
|
16
16
|
jobManager,
|
|
17
17
|
storeConfig,
|
|
18
18
|
workerType,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injectables.js","sourceRoot":"","sources":["../../src/runtime/injectables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAYzD,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"injectables.js","sourceRoot":"","sources":["../../src/runtime/injectables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAYzD,MAAM,CAAC,MAAM,mBAAmB,GAC9B,oBAAoB,CAClB,KAAK,CAAC,MAAM,EACZ,qBAAqB,CACtB,CAAA;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,oBAAoB,CAAY,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;AAE/E,MAAM,CAAC,MAAM,SAAS,GAAG,oBAAoB,CAC3C,KAAK,CAAC,MAAM,EACZ,WAAW,CACZ,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,oBAAoB,CAC5C,KAAK,CAAC,MAAM,EACZ,YAAY,CACb,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,oBAAoB,CAC7C,KAAK,CAAC,MAAM,EACZ,aAAa,CACd,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,oBAAoB,CAC5C,KAAK,CAAC,MAAM,EACZ,YAAY,CACb,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,oBAAoB,CAC/C,KAAK,CAAC,MAAM,EACZ,eAAe,CAChB,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,oBAAoB,CAChD,KAAK,CAAC,MAAM,EACZ,gBAAgB,CACjB,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,oBAAoB,CACjD,KAAK,CAAC,MAAM,EACZ,iBAAiB,CAClB,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,oBAAoB,CAChD,KAAK,CAAC,MAAM,EACZ,gBAAgB,CACjB,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,mBAAmB;IACnB,OAAO;IACP,SAAS;IACT,UAAU;IACV,WAAW;IACX,UAAU;IACV,aAAa;IACb,cAAc;IACd,eAAe;IACf,cAAc;CACf,CAAA"}
|
|
@@ -5,8 +5,8 @@ import type { Applications } from 'nmtjs/runtime/types';
|
|
|
5
5
|
import type { ApplicationConfig } from '../application/config.ts';
|
|
6
6
|
import type { JobWorkerPool, StoreType } from '../enums.ts';
|
|
7
7
|
import type { AnyJob } from '../jobs/job.ts';
|
|
8
|
-
import type { PubSubAdapterType } from '../pubsub/manager.ts';
|
|
9
8
|
import type { JobsSchedulerOptions } from '../scheduler/index.ts';
|
|
9
|
+
import type { SubscriptionAdapterType } from '../subscription/manager.ts';
|
|
10
10
|
import type { StoreTypeOptions } from '../types.ts';
|
|
11
11
|
import { kServerConfig } from '../constants.ts';
|
|
12
12
|
export type ServerPoolOptions = {
|
|
@@ -82,8 +82,8 @@ export interface ServerConfigInit {
|
|
|
82
82
|
};
|
|
83
83
|
jobs?: ServerJobsConfig;
|
|
84
84
|
commands?: {};
|
|
85
|
-
|
|
86
|
-
adapter:
|
|
85
|
+
subscription?: {
|
|
86
|
+
adapter: SubscriptionAdapterType;
|
|
87
87
|
};
|
|
88
88
|
deploymentId?: string;
|
|
89
89
|
metrics?: {
|
|
@@ -144,7 +144,7 @@ export interface ServerConfig {
|
|
|
144
144
|
ui?: ServerJobsConfig['ui'];
|
|
145
145
|
};
|
|
146
146
|
commands?: {};
|
|
147
|
-
|
|
147
|
+
subscription: ServerConfigInit['subscription'];
|
|
148
148
|
deploymentId: ServerConfigInit['deploymentId'];
|
|
149
149
|
metrics?: ServerConfigInit['metrics'];
|
|
150
150
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { kServerConfig } from '../constants.js';
|
|
2
2
|
export function defineServer(options) {
|
|
3
|
-
const { deploymentId, logger, commands, proxy, store, applications,
|
|
3
|
+
const { deploymentId, logger, commands, proxy, store, applications, subscription, metrics, } = options;
|
|
4
4
|
let jobs;
|
|
5
5
|
if (options.jobs) {
|
|
6
6
|
const map = new Map();
|
|
@@ -23,7 +23,7 @@ export function defineServer(options) {
|
|
|
23
23
|
proxy,
|
|
24
24
|
store,
|
|
25
25
|
applications,
|
|
26
|
-
|
|
26
|
+
subscription,
|
|
27
27
|
jobs,
|
|
28
28
|
metrics,
|
|
29
29
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/runtime/server/config.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAgJ/C,MAAM,UAAU,YAAY,CAAC,OAAyB,EAAgB;IACpE,MAAM,EACJ,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,KAAK,EACL,KAAK,EACL,YAAY,EACZ,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/runtime/server/config.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAgJ/C,MAAM,UAAU,YAAY,CAAC,OAAyB,EAAgB;IACpE,MAAM,EACJ,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,KAAK,EACL,KAAK,EACL,YAAY,EACZ,YAAY,EACZ,OAAO,GACR,GAAG,OAAO,CAAA;IAEX,IAAI,IAAsC,CAAA;IAC1C,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAA;QACrC,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QACjE,KAAK,MAAM,EAAE,GAAG,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,IAAI,EAAE;YACzD,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QACxB,IAAI,GAAG;YACL,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK;YACzB,IAAI,EAAE,GAAG;YACT,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS;YACjC,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE;SACpB,CAAA;IACH,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,CAAC,aAAa,CAAC,EAAE,IAAI;QACrB,YAAY;QACZ,MAAM;QACN,QAAQ;QACR,KAAK;QACL,KAAK;QACL,YAAY;QACZ,YAAY;QACZ,IAAI;QACJ,OAAO;KACC,CAAC,CAAA;AAAA,CACZ;AAED,MAAM,UAAU,cAAc,CAAC,KAAU,EAAyB;IAChE,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC,aAAa,CAAC,CAAC,CAAA;AAAA,CACvC"}
|
|
@@ -2,22 +2,22 @@ import { Readable } from 'node:stream';
|
|
|
2
2
|
import type { TAnyEventContract, TAnySubscriptionContract } from '@nmtjs/contract';
|
|
3
3
|
import type { Container, Logger } from '@nmtjs/core';
|
|
4
4
|
import type { t } from '@nmtjs/type';
|
|
5
|
-
export type
|
|
5
|
+
export type SubscriptionAdapterEvent = {
|
|
6
6
|
channel: string;
|
|
7
7
|
payload: any;
|
|
8
8
|
};
|
|
9
|
-
export interface
|
|
9
|
+
export interface SubscriptionAdapterType {
|
|
10
10
|
publish(channel: string, payload: any): Promise<boolean>;
|
|
11
|
-
subscribe(channel: string, signal?: AbortSignal): AsyncGenerator<
|
|
11
|
+
subscribe(channel: string, signal?: AbortSignal): AsyncGenerator<SubscriptionAdapterEvent>;
|
|
12
12
|
initialize(): Promise<void>;
|
|
13
13
|
dispose(): Promise<void>;
|
|
14
14
|
}
|
|
15
|
-
export type
|
|
15
|
+
export type SubscriptionChannel = {
|
|
16
16
|
stream: Readable;
|
|
17
17
|
subscription: TAnySubscriptionContract;
|
|
18
18
|
event: TAnyEventContract;
|
|
19
19
|
};
|
|
20
|
-
export type
|
|
20
|
+
export type SubscribeFn = <Contract extends TAnySubscriptionContract, Events extends {
|
|
21
21
|
[K in keyof Contract['events']]?: true;
|
|
22
22
|
}>(subscription: Contract, events: Events, options: Contract['options'], signal?: AbortSignal) => Promise<Omit<Readable, typeof Symbol.asyncIterator> & {
|
|
23
23
|
[Symbol.asyncIterator]: () => AsyncIterator<{} extends Events ? {
|
|
@@ -32,17 +32,18 @@ export type PubSubSubscribe = <Contract extends TAnySubscriptionContract, Events
|
|
|
32
32
|
} : never;
|
|
33
33
|
}[keyof Events]>;
|
|
34
34
|
}>;
|
|
35
|
-
export type
|
|
36
|
-
export type
|
|
35
|
+
export type PublishFn = <S extends TAnySubscriptionContract, E extends S['events'][keyof S['events']]>(event: E, options: S['options'], data: t.infer.decode.input<E['payload']>) => Promise<boolean>;
|
|
36
|
+
export type SubscriptionManagerOptions = {
|
|
37
37
|
logger: Logger;
|
|
38
38
|
container: Container;
|
|
39
39
|
};
|
|
40
|
-
export declare class
|
|
41
|
-
protected readonly options:
|
|
42
|
-
readonly subscriptions: Map<string,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
export declare class SubscriptionManager {
|
|
41
|
+
protected readonly options: SubscriptionManagerOptions;
|
|
42
|
+
readonly subscriptions: Map<string, SubscriptionChannel>;
|
|
43
|
+
protected readonly logger: Logger;
|
|
44
|
+
constructor(options: SubscriptionManagerOptions);
|
|
45
|
+
protected get adapter(): Promise<SubscriptionAdapterType>;
|
|
46
|
+
subscribe: SubscribeFn;
|
|
47
|
+
publish: PublishFn;
|
|
47
48
|
private createEventStream;
|
|
48
49
|
}
|
|
@@ -2,57 +2,101 @@ import assert from 'node:assert';
|
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
3
|
import { PassThrough, Readable } from 'node:stream';
|
|
4
4
|
import { isAbortError } from '@nmtjs/common';
|
|
5
|
-
import {
|
|
6
|
-
export class
|
|
5
|
+
import { subscriptionAdapter } from '../injectables.js';
|
|
6
|
+
export class SubscriptionManager {
|
|
7
7
|
options;
|
|
8
8
|
subscriptions = new Map();
|
|
9
|
+
logger;
|
|
9
10
|
constructor(options) {
|
|
10
11
|
this.options = options;
|
|
12
|
+
this.logger = options.logger.child({ component: SubscriptionManager.name });
|
|
11
13
|
}
|
|
12
14
|
get adapter() {
|
|
13
|
-
return this.options.container.resolve(
|
|
15
|
+
return this.options.container.resolve(subscriptionAdapter);
|
|
14
16
|
}
|
|
15
17
|
subscribe = async (subscription, events, options, signal) => {
|
|
16
18
|
const adapter = await this.adapter;
|
|
17
19
|
const eventKeys = Object.keys(events).length === 0
|
|
18
20
|
? Object.keys(subscription.events)
|
|
19
21
|
: Object.keys(events);
|
|
22
|
+
this.logger.debug({ subscription: subscription.name, eventCount: eventKeys.length }, 'Opening subscription');
|
|
20
23
|
const streams = Array(eventKeys.length);
|
|
21
24
|
for (const index in eventKeys) {
|
|
22
25
|
const event = subscription.events[eventKeys[index]];
|
|
23
26
|
const channel = getChannelName(event, options);
|
|
24
27
|
if (this.subscriptions.has(channel)) {
|
|
25
28
|
streams[index] = this.subscriptions.get(channel).stream;
|
|
29
|
+
this.logger.trace({
|
|
30
|
+
channel,
|
|
31
|
+
event: event.name,
|
|
32
|
+
activeChannels: this.subscriptions.size,
|
|
33
|
+
}, 'Reusing pubsub channel stream');
|
|
26
34
|
}
|
|
27
35
|
else {
|
|
28
36
|
const iterable = adapter.subscribe(channel, signal);
|
|
29
37
|
const stream = this.createEventStream(iterable);
|
|
30
|
-
stream.on('close', () =>
|
|
38
|
+
stream.on('close', () => {
|
|
39
|
+
this.subscriptions.delete(channel);
|
|
40
|
+
this.logger.debug({
|
|
41
|
+
channel,
|
|
42
|
+
event: event.name,
|
|
43
|
+
activeChannels: this.subscriptions.size,
|
|
44
|
+
}, 'Pubsub channel stream closed');
|
|
45
|
+
});
|
|
46
|
+
stream.on('error', (error) => {
|
|
47
|
+
this.logger.warn({ channel, event: event.name, error }, 'Pubsub channel stream failed');
|
|
48
|
+
});
|
|
31
49
|
streams[index] = stream;
|
|
32
50
|
this.subscriptions.set(channel, { subscription, event, stream });
|
|
51
|
+
this.logger.debug({
|
|
52
|
+
channel,
|
|
53
|
+
event: event.name,
|
|
54
|
+
activeChannels: this.subscriptions.size,
|
|
55
|
+
}, 'Creating channel stream');
|
|
33
56
|
}
|
|
34
57
|
}
|
|
35
|
-
|
|
58
|
+
const mergedStream = mergeEventStreams(streams, signal);
|
|
59
|
+
mergedStream.once('close', () => {
|
|
60
|
+
this.logger.debug({ subscription: subscription.name, eventCount: eventKeys.length }, 'Pubsub subscription stream closed');
|
|
61
|
+
});
|
|
62
|
+
mergedStream.once('error', (error) => {
|
|
63
|
+
this.logger.warn({
|
|
64
|
+
subscription: subscription.name,
|
|
65
|
+
eventCount: eventKeys.length,
|
|
66
|
+
error,
|
|
67
|
+
}, 'Pubsub subscription stream failed');
|
|
68
|
+
});
|
|
69
|
+
return mergedStream;
|
|
36
70
|
};
|
|
37
71
|
publish = async (event, options, data) => {
|
|
38
72
|
const adapter = await this.adapter;
|
|
39
73
|
const channel = getChannelName(event, options);
|
|
74
|
+
this.logger.trace({ channel, event: event.name }, 'Publishing pubsub event');
|
|
40
75
|
try {
|
|
41
76
|
const payload = event.payload.encode(data);
|
|
42
|
-
|
|
77
|
+
const published = await adapter.publish(channel, payload);
|
|
78
|
+
if (published) {
|
|
79
|
+
this.logger.trace({ channel, event: event.name }, 'Published pubsub event');
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
this.logger.warn({ channel, event: event.name }, 'Pubsub adapter reported publish failure');
|
|
83
|
+
}
|
|
84
|
+
return published;
|
|
43
85
|
}
|
|
44
86
|
catch (error) {
|
|
45
|
-
this.
|
|
46
|
-
|
|
87
|
+
this.logger.error({ channel, event: event.name, error }, 'Failed to publish pubsub event');
|
|
88
|
+
throw error;
|
|
47
89
|
}
|
|
48
90
|
};
|
|
49
91
|
createEventStream(iterable) {
|
|
50
92
|
const { subscriptions } = this;
|
|
93
|
+
const logger = this.logger;
|
|
51
94
|
return new Readable({
|
|
52
95
|
objectMode: true,
|
|
53
96
|
read() {
|
|
54
97
|
iterable.next().then(({ value, done }) => {
|
|
55
98
|
if (done) {
|
|
99
|
+
logger.trace('Pubsub adapter stream ended');
|
|
56
100
|
this.push(null);
|
|
57
101
|
}
|
|
58
102
|
else {
|
|
@@ -61,18 +105,25 @@ export class PubSubManager {
|
|
|
61
105
|
const { event } = subscription;
|
|
62
106
|
try {
|
|
63
107
|
const data = event.payload.decode(value.payload);
|
|
108
|
+
logger.trace({ channel: value.channel, event: event.name }, 'Received event');
|
|
64
109
|
this.push({ event: event.name, data });
|
|
65
110
|
}
|
|
66
111
|
catch (error) {
|
|
112
|
+
logger.warn({ channel: value.channel, event: event.name, error }, 'Failed to decode pubsub event payload');
|
|
67
113
|
this.destroy(error);
|
|
68
114
|
}
|
|
69
115
|
}
|
|
116
|
+
else {
|
|
117
|
+
logger.trace({ channel: value.channel }, 'Dropped pubsub event for inactive channel');
|
|
118
|
+
}
|
|
70
119
|
}
|
|
71
120
|
}, (error) => {
|
|
72
121
|
if (isAbortError(error)) {
|
|
122
|
+
logger.trace('Pubsub adapter stream aborted');
|
|
73
123
|
this.push(null);
|
|
74
124
|
}
|
|
75
125
|
else {
|
|
126
|
+
logger.warn({ error }, 'Pubsub adapter stream failed');
|
|
76
127
|
this.destroy(error);
|
|
77
128
|
}
|
|
78
129
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../src/runtime/subscription/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import EventEmitter from 'node:events';
|
|
2
|
+
import type { Logger } from '@nmtjs/core';
|
|
2
3
|
import type { RuntimePlugin } from '../plugin.ts';
|
|
3
4
|
import type { Store } from '../types.ts';
|
|
4
|
-
import type {
|
|
5
|
-
export declare class
|
|
5
|
+
import type { SubscriptionAdapterEvent, SubscriptionAdapterType } from './manager.ts';
|
|
6
|
+
export declare class RedisSubscriptionAdapter implements SubscriptionAdapterType {
|
|
6
7
|
protected readonly client: Store;
|
|
7
8
|
protected readonly events: EventEmitter<[never]>;
|
|
8
9
|
protected readonly listeners: Map<string, number>;
|
|
10
|
+
protected readonly logger?: Logger;
|
|
9
11
|
protected subscriberClient?: Store;
|
|
10
|
-
constructor(client: Store);
|
|
12
|
+
constructor(client: Store, logger?: Logger);
|
|
11
13
|
initialize(): Promise<void>;
|
|
12
14
|
dispose(): Promise<void>;
|
|
13
15
|
publish(channel: string, payload: any): Promise<boolean>;
|
|
14
|
-
subscribe(channel: string, signal?: AbortSignal): AsyncGenerator<
|
|
16
|
+
subscribe(channel: string, signal?: AbortSignal): AsyncGenerator<SubscriptionAdapterEvent>;
|
|
15
17
|
}
|
|
16
|
-
export declare const
|
|
18
|
+
export declare const RedisSubscriptionAdapterPlugin: () => RuntimePlugin;
|
|
@@ -1,95 +1,118 @@
|
|
|
1
1
|
import EventEmitter, { on } from 'node:events';
|
|
2
2
|
import { isAbortError } from '@nmtjs/common';
|
|
3
|
-
import { createFactoryInjectable
|
|
4
|
-
import {
|
|
3
|
+
import { createFactoryInjectable } from '@nmtjs/core';
|
|
4
|
+
import { storeConfig, subscriptionAdapter } from '../injectables.js';
|
|
5
5
|
import { createStoreClient } from '../store/index.js';
|
|
6
|
-
export class
|
|
6
|
+
export class RedisSubscriptionAdapter {
|
|
7
7
|
client;
|
|
8
8
|
events = new EventEmitter();
|
|
9
9
|
listeners = new Map();
|
|
10
|
+
logger;
|
|
10
11
|
subscriberClient;
|
|
11
|
-
constructor(client) {
|
|
12
|
+
constructor(client, logger) {
|
|
12
13
|
this.client = client;
|
|
14
|
+
this.logger = logger?.child({ component: RedisSubscriptionAdapter.name });
|
|
13
15
|
}
|
|
14
16
|
async initialize() {
|
|
17
|
+
this.logger?.debug('Initializing Redis adapter');
|
|
15
18
|
// Create a dedicated subscriber client (Redis requires separate clients for pub/sub)
|
|
16
19
|
this.subscriberClient = this.client.duplicate();
|
|
17
20
|
// Set up message handler
|
|
18
21
|
this.subscriberClient.on('message', (channel, message) => {
|
|
19
22
|
try {
|
|
20
23
|
const parsed = JSON.parse(message);
|
|
24
|
+
this.logger?.trace({ channel }, 'Received Redis message');
|
|
21
25
|
this.events.emit(channel, parsed);
|
|
22
26
|
}
|
|
23
|
-
catch {
|
|
27
|
+
catch (error) {
|
|
28
|
+
this.logger?.warn({ channel, error }, 'Failed to parse Redis message');
|
|
29
|
+
}
|
|
24
30
|
});
|
|
31
|
+
this.logger?.debug('Redis adapter initialized');
|
|
25
32
|
}
|
|
26
33
|
async dispose() {
|
|
34
|
+
this.logger?.debug('Disposing Redis adapter');
|
|
27
35
|
if (this.subscriberClient) {
|
|
28
36
|
await this.subscriberClient.quit();
|
|
29
37
|
this.subscriberClient = undefined;
|
|
30
38
|
}
|
|
39
|
+
this.logger?.debug('Redis adapter disposed');
|
|
31
40
|
}
|
|
32
41
|
async publish(channel, payload) {
|
|
42
|
+
this.logger?.trace({ channel }, 'Publishing Redis message');
|
|
33
43
|
try {
|
|
34
44
|
await this.client.publish(channel, JSON.stringify(payload));
|
|
45
|
+
this.logger?.trace({ channel }, 'Published Redis message');
|
|
35
46
|
return true;
|
|
36
47
|
}
|
|
37
|
-
catch {
|
|
48
|
+
catch (error) {
|
|
49
|
+
this.logger?.warn({ channel, error }, 'Failed to publish Redis message');
|
|
38
50
|
return false;
|
|
39
51
|
}
|
|
40
52
|
}
|
|
41
53
|
async *subscribe(channel, signal) {
|
|
42
54
|
if (!this.subscriberClient) {
|
|
43
|
-
throw new Error('
|
|
55
|
+
throw new Error('RedisSubscriptionAdapter not initialized');
|
|
44
56
|
}
|
|
57
|
+
this.logger?.debug({ channel }, 'Opening Redis channel listener');
|
|
45
58
|
if (!this.listeners.has(channel)) {
|
|
46
59
|
await this.subscriberClient.subscribe(channel);
|
|
47
60
|
this.listeners.set(channel, 1);
|
|
61
|
+
this.logger?.debug({ channel, listeners: 1 }, 'Subscribed Redis channel');
|
|
48
62
|
}
|
|
49
63
|
else {
|
|
50
|
-
|
|
64
|
+
const listeners = this.listeners.get(channel) + 1;
|
|
65
|
+
this.listeners.set(channel, listeners);
|
|
66
|
+
this.logger?.trace({ channel, listeners }, 'Reusing Redis channel listener');
|
|
51
67
|
}
|
|
52
68
|
try {
|
|
53
69
|
signal?.throwIfAborted();
|
|
54
70
|
for await (const [payload] of on(this.events, channel, { signal })) {
|
|
71
|
+
this.logger?.trace({ channel }, 'Delivering Redis message');
|
|
55
72
|
yield { channel, payload };
|
|
56
73
|
}
|
|
57
74
|
}
|
|
58
75
|
catch (error) {
|
|
59
|
-
if (isAbortError(error))
|
|
76
|
+
if (isAbortError(error)) {
|
|
77
|
+
this.logger?.trace({ channel }, 'Redis channel listener aborted');
|
|
60
78
|
throw error;
|
|
79
|
+
}
|
|
80
|
+
this.logger?.warn({ channel, error }, 'Redis channel listener failed');
|
|
61
81
|
}
|
|
62
82
|
finally {
|
|
63
83
|
const count = this.listeners.get(channel);
|
|
64
84
|
if (count !== undefined) {
|
|
65
85
|
if (count > 1) {
|
|
66
|
-
|
|
86
|
+
const listeners = count - 1;
|
|
87
|
+
this.listeners.set(channel, listeners);
|
|
88
|
+
this.logger?.trace({ channel, listeners }, 'Detached Redis channel listener');
|
|
67
89
|
}
|
|
68
90
|
else {
|
|
69
91
|
await this.subscriberClient?.unsubscribe(channel);
|
|
70
92
|
this.listeners.delete(channel);
|
|
93
|
+
this.logger?.debug({ channel, listeners: 0 }, 'Unsubscribed Redis channel');
|
|
71
94
|
}
|
|
72
95
|
}
|
|
73
96
|
}
|
|
74
97
|
}
|
|
75
98
|
}
|
|
76
|
-
export const
|
|
99
|
+
export const RedisSubscriptionAdapterPlugin = () => {
|
|
77
100
|
return {
|
|
78
|
-
name: '
|
|
101
|
+
name: 'redis-subscription-adapter',
|
|
79
102
|
hooks: {
|
|
80
103
|
'lifecycle:beforeInitialize': async (ctx) => {
|
|
81
104
|
const adapter = await ctx.container.resolve(createFactoryInjectable({
|
|
82
105
|
dependencies: { config: storeConfig },
|
|
83
106
|
factory: async ({ config }) => {
|
|
84
107
|
const connection = await createStoreClient(config);
|
|
85
|
-
const adapter = new
|
|
108
|
+
const adapter = new RedisSubscriptionAdapter(connection, ctx.logger);
|
|
86
109
|
await adapter.initialize();
|
|
87
110
|
return { adapter, connection };
|
|
88
111
|
},
|
|
89
112
|
pick: ({ adapter }) => adapter,
|
|
90
113
|
dispose: ({ connection }) => connection.quit(),
|
|
91
114
|
}));
|
|
92
|
-
ctx.container.provide(
|
|
115
|
+
ctx.container.provide(subscriptionAdapter, adapter);
|
|
93
116
|
},
|
|
94
117
|
},
|
|
95
118
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../../../src/runtime/subscription/redis.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,12 +2,12 @@ import type { WorkerType } from '../enums.ts';
|
|
|
2
2
|
import type { BaseRuntimeOptions } from '../runtime.ts';
|
|
3
3
|
import type { ServerConfig } from '../server/config.ts';
|
|
4
4
|
import { JobManager } from '../jobs/manager.ts';
|
|
5
|
-
import { PubSubManager } from '../pubsub/manager.ts';
|
|
6
5
|
import { BaseRuntime } from '../runtime.ts';
|
|
6
|
+
import { SubscriptionManager } from '../subscription/manager.ts';
|
|
7
7
|
export declare abstract class BaseWorkerRuntime extends BaseRuntime {
|
|
8
8
|
readonly config: ServerConfig;
|
|
9
9
|
readonly workerType: WorkerType;
|
|
10
|
-
|
|
10
|
+
subscriptionManager: SubscriptionManager;
|
|
11
11
|
jobManager?: JobManager;
|
|
12
12
|
constructor(config: ServerConfig, options: BaseRuntimeOptions, workerType: WorkerType);
|
|
13
13
|
initialize(): Promise<void>;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { CoreInjectables, provision } from '@nmtjs/core';
|
|
2
2
|
import * as injectables from '../injectables.js';
|
|
3
3
|
import { JobManager } from '../jobs/manager.js';
|
|
4
|
-
import { PubSubManager } from '../pubsub/manager.js';
|
|
5
4
|
import { BaseRuntime } from '../runtime.js';
|
|
5
|
+
import { SubscriptionManager } from '../subscription/manager.js';
|
|
6
6
|
export class BaseWorkerRuntime extends BaseRuntime {
|
|
7
7
|
config;
|
|
8
8
|
workerType;
|
|
9
|
-
|
|
9
|
+
subscriptionManager;
|
|
10
10
|
jobManager;
|
|
11
11
|
constructor(config, options, workerType) {
|
|
12
12
|
super(options);
|
|
13
13
|
this.config = config;
|
|
14
14
|
this.workerType = workerType;
|
|
15
|
-
this.
|
|
15
|
+
this.subscriptionManager = new SubscriptionManager({
|
|
16
16
|
logger: this.logger,
|
|
17
17
|
container: this.container,
|
|
18
18
|
});
|
|
@@ -24,8 +24,8 @@ export class BaseWorkerRuntime extends BaseRuntime {
|
|
|
24
24
|
const injections = [
|
|
25
25
|
provision(CoreInjectables.logger, this.logger),
|
|
26
26
|
provision(injectables.workerType, this.workerType),
|
|
27
|
-
provision(injectables.
|
|
28
|
-
provision(injectables.
|
|
27
|
+
provision(injectables.publish, this.subscriptionManager.publish.bind(this.subscriptionManager)),
|
|
28
|
+
provision(injectables.subscribe, this.subscriptionManager.subscribe.bind(this.subscriptionManager)),
|
|
29
29
|
];
|
|
30
30
|
if (this.config.store) {
|
|
31
31
|
injections.push(provision(injectables.storeConfig, this.config.store));
|