@fluojs/event-bus 1.0.0 → 2.0.0
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.ko.md +47 -5
- package/README.md +48 -6
- package/dist/service.d.ts +8 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +125 -26
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
package/README.ko.md
CHANGED
|
@@ -52,7 +52,7 @@ export class NotificationService {
|
|
|
52
52
|
|
|
53
53
|
`EventBusModule`을 등록하고 `EventBusLifecycleService`를 주입받아 이벤트를 발행합니다.
|
|
54
54
|
|
|
55
|
-
인프로세스 이벤트 버스 등록은 `EventBusModule.forRoot(...)`로 구성합니다.
|
|
55
|
+
인프로세스 이벤트 버스 등록은 `EventBusModule.forRoot(...)`로 구성합니다. Event-bus provider는 기본적으로 global(`global: true`)이므로 root graph를 import하는 모듈에서 `EventBusLifecycleService`와 `EVENT_BUS` 호환성 토큰을 사용할 수 있습니다. 모듈-local visibility가 필요하면 `EventBusModule.forRoot({ global: false })`를 전달하세요.
|
|
56
56
|
|
|
57
57
|
```typescript
|
|
58
58
|
import { Module, Inject } from '@fluojs/core';
|
|
@@ -75,7 +75,9 @@ export class UserService {
|
|
|
75
75
|
export class AppModule {}
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
`publish(event, options?)`는 `signal`, `timeoutMs`, `waitForHandlers`를 지원합니다. `waitForHandlers`의 기본값은 `true`이며, 기다리는 로컬 핸들러와 기다리는 트랜스포트 publish는 동일한 timeout 및 cancellation bound를 공유합니다. `waitForHandlers`를 `false`로 설정하면 publish가 즉시 반환되고 timeout bound를 적용하지
|
|
78
|
+
`publish(event, options?)`는 `signal`, `timeoutMs`, `waitForHandlers`를 지원합니다. `waitForHandlers`의 기본값은 `true`이며, 기다리는 로컬 핸들러와 기다리는 트랜스포트 publish는 동일한 timeout 및 cancellation bound를 공유합니다. 이러한 bound가 실제 handler 또는 transport 작업이 끝나기 전에 호출자에게 반환되는 publish promise를 settle하더라도, shutdown은 해당 underlying awaited work가 settle되거나 shutdown drain bound가 만료될 때까지 계속 추적합니다. `waitForHandlers`를 `false`로 설정하면 publish가 즉시 반환되고 timeout bound를 적용하지 않지만, handler와 transport 작업은 background에서 계속 실행되며 shutdown drain 추적 대상에 남습니다. Shutdown 중에는 이벤트 버스가 진행 중인 awaited/background publish 및 inbound transport handler 작업을 drain한 뒤 트랜스포트를 닫고, lifecycle이 stopping에 진입한 뒤의 새 publish 호출과 shutdown 시작 뒤 도착한 inbound transport callback은 무시합니다. Shutdown drain은 기본값이 5000ms인 `EventBusModule.forRoot({ shutdown: { drainTimeoutMs } })`로 제한됩니다. 활성 dispatch 작업이 이 bound 이후에도 멈춰 있으면 bus는 degraded status diagnostic을 기록하고 경고를 남긴 뒤, 애플리케이션 close를 무기한 hang시키지 않고 transport cleanup을 계속합니다.
|
|
79
|
+
|
|
80
|
+
**마이그레이션 참고:** `waitForHandlers: false`를 사용하는 애플리케이션은 이제 background handler 및 transport 작업을 위해 `app.close()`가 최대 `shutdown.drainTimeoutMs`까지 기다린 뒤 transport cleanup을 계속할 수 있음을 shutdown budget에 반영해야 합니다. 해당 작업을 bounded하게 유지하거나 애플리케이션에 적절한 drain budget을 구성하세요.
|
|
79
81
|
|
|
80
82
|
## 일반적인 패턴
|
|
81
83
|
|
|
@@ -94,6 +96,46 @@ EventBusModule.forRoot({
|
|
|
94
96
|
})
|
|
95
97
|
```
|
|
96
98
|
|
|
99
|
+
Redis Pub/Sub은 durable work queue가 아니라 fan-out transport입니다. 여러 애플리케이션 인스턴스가 같은 이벤트 채널을 구독하면 각 인스턴스가 같은 published fact를 볼 수 있습니다. 따라서 상태를 변경하거나 알림을 보내거나 외부 시스템을 호출하는 handler는 idempotent해야 합니다. Payload에 안정적인 event identifier 또는 business key를 담고, 이미 적용한 reaction을 기록하며, 반복 전달이 side effect를 두 번 실행하는 대신 같은 결과로 수렴하도록 만드세요.
|
|
100
|
+
|
|
101
|
+
`@OnEvent(...)` handler는 작고 bounded하게 유지하세요. 빠른 local projection, cache invalidation, 가벼운 notification처럼 publish timeout과 shutdown drain window 안에 끝낼 수 있는 reaction에 적합합니다. Reaction이 느리거나, failure-prone이거나, retry 가능하거나, operator-visible dead-letter handling이 필요하다면 해당 작업을 inline으로 수행하지 말고 event handler에서 `@fluojs/queue`의 durable job으로 hand off하세요. Handoff에는 애플리케이션이 소유한 unique claim을 사용하고, `queue.enqueue(...)`가 성공한 뒤에만 handoff를 enqueued로 표시하세요. Enqueue가 실패하면 pending claim을 해제해 이후 duplicate event가 안전하게 다시 시도할 수 있게 합니다.
|
|
102
|
+
|
|
103
|
+
아래 예제의 `this.reactions` helper는 `@fluojs/event-bus`나 `@fluojs/queue` API가 아니라 애플리케이션이 소유한 claim store를 나타냅니다. Business key를 atomic하게 claim하고 stale pending claim을 애플리케이션의 retry policy에 따라 복구할 수 있는 저장소로 구현하세요.
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
import { Inject } from '@fluojs/core';
|
|
107
|
+
import { OnEvent } from '@fluojs/event-bus';
|
|
108
|
+
import { QueueLifecycleService } from '@fluojs/queue';
|
|
109
|
+
|
|
110
|
+
export class GenerateInvoiceJob {
|
|
111
|
+
constructor(public readonly orderId: string) {}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@Inject(QueueLifecycleService)
|
|
115
|
+
export class BillingEventsHandler {
|
|
116
|
+
constructor(private readonly queue: QueueLifecycleService) {}
|
|
117
|
+
|
|
118
|
+
@OnEvent(OrderPlacedEvent)
|
|
119
|
+
async enqueueInvoice(event: OrderPlacedEvent) {
|
|
120
|
+
const handoffKey = `${event.orderId}:invoice`;
|
|
121
|
+
|
|
122
|
+
if (!(await this.reactions.claimPending(handoffKey))) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
await this.queue.enqueue(new GenerateInvoiceJob(event.orderId));
|
|
128
|
+
await this.reactions.markEnqueued(handoffKey);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
await this.reactions.releasePending(handoffKey);
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
비즈니스 사실이 발생했음을 표현할 때는 event bus를 사용하세요. Reaction에 retry, backoff, workload isolation, dead-letter inspection이 필요하면 Queue를 사용하세요. Claim이 pending인 동안 프로세스가 종료될 수 있다면 애플리케이션의 retry policy에 맞게 stale pending record를 복구하도록 애플리케이션 소유 claim store를 설계하세요.
|
|
138
|
+
|
|
97
139
|
### 버전이 명시된 이벤트 키
|
|
98
140
|
|
|
99
141
|
`static eventKey`를 사용하여 클래스 이름 변경이나 코드 압축(minification)과 관계없이 안정적인 채널 이름을 유지할 수 있습니다.
|
|
@@ -104,12 +146,12 @@ class UserRegisteredEvent {
|
|
|
104
146
|
}
|
|
105
147
|
```
|
|
106
148
|
|
|
107
|
-
핸들러는 imported module의 singleton provider와 controller에서 발견됩니다. 각 핸들러는 격리된 clone payload를 받으며, class inheritance는 `instanceof` 매칭으로 지원됩니다. 외부 트랜스포트를 구성하면 subclass event publish는 publisher process에 해당 타입의 local handler가 없더라도 subclass channel과 prototype chain의 모든 inherited event channel로 fan-out됩니다. Subclass가 직접 `static eventKey`를 선언한 경우에만 그 값을 사용하며, 그렇지 않으면 subclass channel은 class name을 유지하고 base class는 자신의 stable key를 유지합니다.
|
|
149
|
+
핸들러는 imported module의 singleton provider와 controller에서 발견됩니다. Discovery는 여러 provider가 같은 구현 class를 공유하더라도 서로 다른 singleton provider identity를 유지하며, 같은 provider token과 handler method가 중복 등록된 경우에는 한 번만 호출합니다. Event-bus bootstrap은 ready 상태를 보고하기 전에 발견된 모든 handler target을 resolve하며, 실제 handler target resolution이 실패하면 handler를 조용히 건너뛰고 ready를 보고하는 대신 bootstrap을 실패시킵니다. Discovery는 이미 handler metadata를 가진 singleton `useValue` instance와 provider token 자체가 `@OnEvent(...)` metadata를 가진 handler class인 singleton `useFactory` provider만 검사하므로, event-bus bootstrap 중 관련 없는 factory provider는 호출되지 않습니다. 각 핸들러는 격리된 clone payload를 받으며, class inheritance는 `instanceof` 매칭으로 지원됩니다. 외부 트랜스포트를 구성하면 subclass event publish는 publisher process에 해당 타입의 local handler가 없더라도 subclass channel과 prototype chain의 모든 inherited event channel로 fan-out됩니다. Subclass가 직접 `static eventKey`를 선언한 경우에만 그 값을 사용하며, 그렇지 않으면 subclass channel은 class name을 유지하고 base class는 자신의 stable key를 유지합니다.
|
|
108
150
|
|
|
109
151
|
## 공개 API 개요
|
|
110
152
|
|
|
111
153
|
### 핵심 구성 요소
|
|
112
|
-
- `EventBusModule.forRoot(
|
|
154
|
+
- `EventBusModule.forRoot({ global?, publish?, shutdown?, transport? })`: 이벤트 버스 등록을 위한 기본 진입점입니다. `global`의 기본값은 `true`이며, event-bus provider를 event-bus 모듈을 import한 모듈을 통해서만 보이게 하려면 `global: false`를 설정하세요.
|
|
113
155
|
- `EventBusLifecycleService`: 이벤트 발행(`publish(event, options?)`)과 platform status snapshot 생성을 위한 기본 서비스입니다.
|
|
114
156
|
- `@OnEvent(EventClass)`: 특정 메서드를 이벤트 핸들러로 지정하는 데코레이터입니다.
|
|
115
157
|
- `EVENT_BUS`: 발행 facade를 위한 호환성 주입 토큰입니다.
|
|
@@ -120,7 +162,7 @@ class UserRegisteredEvent {
|
|
|
120
162
|
- `EventBus`, `EventPublishOptions`, `EventBusModuleOptions`, `EventType`: 발행, 기본값, 트랜스포트, 안정적인 이벤트 키를 위한 타입 전용 계약입니다.
|
|
121
163
|
- `EventBusLifecycleState`, `EventBusStatusAdapterInput`, `EventBusPlatformStatusSnapshot`: status snapshot 계약입니다.
|
|
122
164
|
|
|
123
|
-
Transport bootstrap은 unique event channel마다 한 번만 subscribe합니다. `eventKey`가 있으면 transport channel 이름을 제어합니다. 잘못된 JSON transport message는 무시되며, shutdown 시작 뒤 도착한 inbound transport message는 local handler dispatch 전에 무시됩니다.
|
|
165
|
+
Transport bootstrap은 unique event channel마다 한 번만 subscribe합니다. `eventKey`가 있으면 transport channel 이름을 제어합니다. Bootstrap 중 이후 transport subscription이 실패하면 이벤트 버스는 이미 열린 channel을 rollback하기 위해 subscription error를 다시 던지기 전에 transport를 닫습니다. 잘못된 JSON transport message는 무시되며, shutdown 시작 뒤 도착한 inbound transport message는 local handler dispatch 전에 무시됩니다.
|
|
124
166
|
|
|
125
167
|
## 런타임별 및 통합 서브패스
|
|
126
168
|
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ In-process event publishing and subscription for fluo. It features decorator-bas
|
|
|
10
10
|
- [When to use](#when-to-use)
|
|
11
11
|
- [Quick Start](#quick-start)
|
|
12
12
|
- [Common Patterns](#common-patterns)
|
|
13
|
-
- [Public API](#public-api)
|
|
13
|
+
- [Public API Overview](#public-api-overview)
|
|
14
14
|
- [Runtime-Specific and Integration Subpaths](#runtime-specific-and-integration-subpaths)
|
|
15
15
|
- [Related Packages](#related-packages)
|
|
16
16
|
- [Example Sources](#example-sources)
|
|
@@ -52,7 +52,7 @@ export class NotificationService {
|
|
|
52
52
|
|
|
53
53
|
Import `EventBusModule` and inject `EventBusLifecycleService` to publish events.
|
|
54
54
|
|
|
55
|
-
Use `EventBusModule.forRoot(...)` to wire the in-process event bus.
|
|
55
|
+
Use `EventBusModule.forRoot(...)` to wire the in-process event bus. Event-bus providers are global by default (`global: true`), so `EventBusLifecycleService` and the `EVENT_BUS` compatibility token are visible to modules that import the root graph. Pass `EventBusModule.forRoot({ global: false })` when you need module-local visibility instead.
|
|
56
56
|
|
|
57
57
|
```typescript
|
|
58
58
|
import { Module, Inject } from '@fluojs/core';
|
|
@@ -75,7 +75,9 @@ export class UserService {
|
|
|
75
75
|
export class AppModule {}
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
`publish(event, options?)` supports `signal`, `timeoutMs`, and `waitForHandlers`. `waitForHandlers` defaults to `true`; awaited local handlers and awaited transport publishes share the same timeout and cancellation bounds. When `waitForHandlers` is set to `false`, publishing returns immediately and skips timeout bounds. During shutdown, the event bus drains in-flight awaited publish
|
|
78
|
+
`publish(event, options?)` supports `signal`, `timeoutMs`, and `waitForHandlers`. `waitForHandlers` defaults to `true`; awaited local handlers and awaited transport publishes share the same timeout and cancellation bounds. When those bounds settle the caller-facing publish promise before the underlying handler or transport work finishes, shutdown still tracks that underlying awaited work until it settles or the shutdown drain bound expires. When `waitForHandlers` is set to `false`, publishing returns immediately and skips timeout bounds, while the handler and transport work continue in the background and remain part of shutdown drain tracking. During shutdown, the event bus drains in-flight awaited and background publish work plus inbound transport handler work before closing the transport, ignores new publish calls after the lifecycle has started stopping, and ignores inbound transport callbacks that arrive after shutdown begins. Shutdown drain is bounded by `EventBusModule.forRoot({ shutdown: { drainTimeoutMs } })`, which defaults to 5000ms; if active dispatch work is still stuck after the bound, the bus records a degraded status diagnostic, logs a warning, and continues transport cleanup instead of hanging application close indefinitely.
|
|
79
|
+
|
|
80
|
+
**Migration note:** applications that use `waitForHandlers: false` should now budget for `app.close()` to wait up to `shutdown.drainTimeoutMs` for background handler and transport work before transport cleanup continues. Keep that work bounded or configure a drain budget appropriate for the application.
|
|
79
81
|
|
|
80
82
|
## Common Patterns
|
|
81
83
|
|
|
@@ -94,6 +96,46 @@ EventBusModule.forRoot({
|
|
|
94
96
|
})
|
|
95
97
|
```
|
|
96
98
|
|
|
99
|
+
Redis Pub/Sub is a fan-out transport, not a durable work queue. When multiple application instances subscribe to the same event channel, each instance can see the same published fact. Handlers that mutate state, send notifications, or call external systems should therefore be idempotent: carry a stable event identifier or business key in the payload, record which reactions have already been applied, and make repeat deliveries converge to the same result instead of performing the side effect twice.
|
|
100
|
+
|
|
101
|
+
Keep `@OnEvent(...)` handlers small and bounded. They are a good fit for fast local projections, cache invalidation, lightweight notifications, and other reactions that can finish within the publish timeout and shutdown drain window. If a reaction is slow, failure-prone, retryable, or needs operator-visible dead-letter handling, hand off a durable job to `@fluojs/queue` from the event handler instead of doing the work inline. Use an application-owned unique claim for the handoff, then mark the handoff as enqueued only after `queue.enqueue(...)` succeeds; if enqueue fails, release the pending claim so a later duplicate event can retry safely.
|
|
102
|
+
|
|
103
|
+
The `this.reactions` helper in the example below represents an application-owned claim store, not an API from `@fluojs/event-bus` or `@fluojs/queue`. Back it with storage that can atomically claim a business key and recover stale pending claims according to your application's retry policy.
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
import { Inject } from '@fluojs/core';
|
|
107
|
+
import { OnEvent } from '@fluojs/event-bus';
|
|
108
|
+
import { QueueLifecycleService } from '@fluojs/queue';
|
|
109
|
+
|
|
110
|
+
export class GenerateInvoiceJob {
|
|
111
|
+
constructor(public readonly orderId: string) {}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@Inject(QueueLifecycleService)
|
|
115
|
+
export class BillingEventsHandler {
|
|
116
|
+
constructor(private readonly queue: QueueLifecycleService) {}
|
|
117
|
+
|
|
118
|
+
@OnEvent(OrderPlacedEvent)
|
|
119
|
+
async enqueueInvoice(event: OrderPlacedEvent) {
|
|
120
|
+
const handoffKey = `${event.orderId}:invoice`;
|
|
121
|
+
|
|
122
|
+
if (!(await this.reactions.claimPending(handoffKey))) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
await this.queue.enqueue(new GenerateInvoiceJob(event.orderId));
|
|
128
|
+
await this.reactions.markEnqueued(handoffKey);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
await this.reactions.releasePending(handoffKey);
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Use the event bus to state that a business fact happened. Use Queue when the reaction needs retry, backoff, workload isolation, or dead-letter inspection. If the process can crash while a claim is pending, make the application-owned claim store recover stale pending records according to your application's retry policy.
|
|
138
|
+
|
|
97
139
|
### Versioned Event Keys
|
|
98
140
|
|
|
99
141
|
Use static `eventKey` to ensure stable channel names regardless of class minification or renames.
|
|
@@ -104,12 +146,12 @@ class UserRegisteredEvent {
|
|
|
104
146
|
}
|
|
105
147
|
```
|
|
106
148
|
|
|
107
|
-
Handlers are discovered from singleton providers and controllers across imported modules. Each handler receives an isolated cloned payload, and class inheritance is supported through `instanceof` matching. With an external transport configured, publishing a subclass event fans out to the subclass channel and every inherited event channel in its prototype chain, even when the publisher process has no matching local handlers for those types. A subclass uses its own `static eventKey` only when it declares one directly; otherwise its class name remains the subclass channel while base classes keep their own stable keys.
|
|
149
|
+
Handlers are discovered from singleton providers and controllers across imported modules. Discovery keeps distinct singleton provider identities even when multiple providers share the same implementation class; duplicate registration of the same provider token and handler method is invoked only once. Event-bus bootstrap resolves every discovered handler target before reporting ready, and a real handler target resolution failure fails bootstrap instead of silently reporting ready with skipped handlers. Discovery inspects singleton `useValue` instances that already carry handler metadata and singleton `useFactory` providers only when their provider token is the handler class with `@OnEvent(...)` metadata, so unrelated factory providers are not invoked during event-bus bootstrap. Each handler receives an isolated cloned payload, and class inheritance is supported through `instanceof` matching. With an external transport configured, publishing a subclass event fans out to the subclass channel and every inherited event channel in its prototype chain, even when the publisher process has no matching local handlers for those types. A subclass uses its own `static eventKey` only when it declares one directly; otherwise its class name remains the subclass channel while base classes keep their own stable keys.
|
|
108
150
|
|
|
109
151
|
## Public API Overview
|
|
110
152
|
|
|
111
153
|
### Core
|
|
112
|
-
- `EventBusModule.forRoot(
|
|
154
|
+
- `EventBusModule.forRoot({ global?, publish?, shutdown?, transport? })`: Main entry point for event bus registration. `global` defaults to `true`; set `global: false` to keep event-bus providers visible only through the module that imports the event-bus module.
|
|
113
155
|
- `EventBusLifecycleService`: Primary service for publishing events (`publish(event, options?)`) and creating platform status snapshots.
|
|
114
156
|
- `@OnEvent(EventClass)`: Decorator to mark a method as an event handler.
|
|
115
157
|
- `EVENT_BUS`: Compatibility injection token for the publish facade.
|
|
@@ -120,7 +162,7 @@ Handlers are discovered from singleton providers and controllers across imported
|
|
|
120
162
|
- `EventBus`, `EventPublishOptions`, `EventBusModuleOptions`, `EventType`: Type-only contracts for publishing, defaults, transports, and stable event keys.
|
|
121
163
|
- `EventBusLifecycleState`, `EventBusStatusAdapterInput`, `EventBusPlatformStatusSnapshot`: Status snapshot contracts.
|
|
122
164
|
|
|
123
|
-
Transport bootstrap subscribes once per unique event channel. `eventKey` controls the transport channel name when present. Invalid JSON transport messages are ignored, and inbound transport messages that arrive after shutdown starts are ignored before local handler dispatch.
|
|
165
|
+
Transport bootstrap subscribes once per unique event channel. `eventKey` controls the transport channel name when present. If a later transport subscription fails during bootstrap, the event bus closes the transport to roll back any channels that were already opened before rethrowing the subscription error. Invalid JSON transport messages are ignored, and inbound transport messages that arrive after shutdown starts are ignored before local handler dispatch.
|
|
124
166
|
|
|
125
167
|
## Runtime-Specific and Integration Subpaths
|
|
126
168
|
|
package/dist/service.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Container } from '@fluojs/di';
|
|
2
|
-
import {
|
|
2
|
+
import type { ApplicationLogger, CompiledModule, OnApplicationBootstrap, OnApplicationShutdown } from '@fluojs/runtime';
|
|
3
3
|
import type { EventBus, EventBusModuleOptions, EventPublishOptions } from './types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Lifecycle-managed in-process event bus with optional external transport fan-out.
|
|
@@ -24,6 +24,7 @@ export declare class EventBusLifecycleService implements EventBus, OnApplication
|
|
|
24
24
|
private shutdownDrainTimeouts;
|
|
25
25
|
private readonly activeDispatches;
|
|
26
26
|
private readonly transport;
|
|
27
|
+
private transportClosed;
|
|
27
28
|
constructor(runtimeContainer: Container, compiledModules: readonly CompiledModule[], logger: ApplicationLogger, moduleOptions: EventBusModuleOptions);
|
|
28
29
|
onApplicationBootstrap(): Promise<void>;
|
|
29
30
|
onApplicationShutdown(): Promise<void>;
|
|
@@ -45,6 +46,7 @@ export declare class EventBusLifecycleService implements EventBus, OnApplication
|
|
|
45
46
|
private canPublishInCurrentLifecycle;
|
|
46
47
|
private drainActiveDispatches;
|
|
47
48
|
private trackActiveDispatch;
|
|
49
|
+
private trackActiveDispatchWork;
|
|
48
50
|
private awaitShutdownDrain;
|
|
49
51
|
private resolveShutdownDrainTimeoutMs;
|
|
50
52
|
private matchEventDescriptors;
|
|
@@ -63,6 +65,9 @@ export declare class EventBusLifecycleService implements EventBus, OnApplication
|
|
|
63
65
|
private logTransportPublishCancelledBeforeDispatch;
|
|
64
66
|
private logBoundedTransportPublishError;
|
|
65
67
|
private subscribeTransportChannels;
|
|
68
|
+
private rollbackTransportSubscriptionsAfterBootstrapFailure;
|
|
69
|
+
private closeTransportOrRecordFailure;
|
|
70
|
+
private closeTransport;
|
|
66
71
|
private subscribeTransportChannel;
|
|
67
72
|
private canDispatchIncomingTransportMessage;
|
|
68
73
|
private dispatchIncomingTransportMessage;
|
|
@@ -79,6 +84,8 @@ export declare class EventBusLifecycleService implements EventBus, OnApplication
|
|
|
79
84
|
private isDuplicateHandlerRegistration;
|
|
80
85
|
private createHandlerDescriptor;
|
|
81
86
|
private discoveryCandidates;
|
|
87
|
+
private resolveProviderDiscoveryCandidate;
|
|
88
|
+
private createUnresolvedProviderDiscoveryCandidate;
|
|
82
89
|
private invokeHandler;
|
|
83
90
|
private resolveHandlerInstance;
|
|
84
91
|
}
|
package/dist/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,YAAY,CAAC;AACtD,OAAO,
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAMxH,OAAO,KAAK,EACV,QAAQ,EACR,qBAAqB,EAGrB,mBAAmB,EAEpB,MAAM,YAAY,CAAC;AA6EpB;;;;;GAKG;AACH,qBACa,wBAAyB,YAAW,QAAQ,EAAE,sBAAsB,EAAE,qBAAqB;IAgBpG,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAlBhC,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,gBAAgB,CAA4B;IACpD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,cAAc,CAAsF;IAC5G,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAsC;IACvE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IACxD,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,wBAAwB,CAAK;IACrC,OAAO,CAAC,0BAA0B,CAAK;IACvC,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA4B;IAC7D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;IAC1D,OAAO,CAAC,eAAe,CAAS;gBAGb,gBAAgB,EAAE,SAAS,EAC3B,eAAe,EAAE,SAAS,cAAc,EAAE,EAC1C,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,qBAAqB;IAKjD,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAavC,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB5C;;;;OAIG;IACH,4BAA4B;IAe5B;;;;;;OAMG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;YAY5D,cAAc;IA+B5B,OAAO,CAAC,4BAA4B;YAItB,qBAAqB;YAcrB,mBAAmB;IAUjC,OAAO,CAAC,uBAAuB;YAajB,kBAAkB;IAiBhC,OAAO,CAAC,6BAA6B;IAIrC,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,qBAAqB;IAW7B,OAAO,CAAC,+BAA+B;IAWvC,OAAO,CAAC,8BAA8B;YAMxB,yBAAyB;YAazB,gBAAgB;IAqB9B,OAAO,CAAC,qBAAqB;IAY7B,OAAO,CAAC,kBAAkB;YAQZ,gBAAgB;IAW9B,OAAO,CAAC,oBAAoB;IAY5B,OAAO,CAAC,2BAA2B;IAkBnC,OAAO,CAAC,gBAAgB;YAiBV,kBAAkB;IAgChC,OAAO,CAAC,0CAA0C;IAOlD,OAAO,CAAC,+BAA+B;YAwBzB,0BAA0B;YAwB1B,mDAAmD;YAInD,6BAA6B;YAa7B,cAAc;YAYd,yBAAyB;IAiCvC,OAAO,CAAC,mCAAmC;YAI7B,gCAAgC;YAmBhC,uBAAuB;YAUvB,uBAAuB;IAmBrC,OAAO,CAAC,iCAAiC;IAOzC,OAAO,CAAC,yBAAyB;YAwBnB,qBAAqB;IAuBnC,OAAO,CAAC,sBAAsB;IAqB9B,OAAO,CAAC,kBAAkB;IAiB1B,OAAO,CAAC,gBAAgB;YAmBV,0BAA0B;IAyBxC,OAAO,CAAC,+BAA+B;IAevC,OAAO,CAAC,8BAA8B;IA4BtC,OAAO,CAAC,uBAAuB;YAejB,mBAAmB;IAoDjC,OAAO,CAAC,iCAAiC;IA+CzC,OAAO,CAAC,0CAA0C;YAmBpC,aAAa;YAwBb,sBAAsB;CAsBrC"}
|
package/dist/service.js
CHANGED
|
@@ -44,6 +44,12 @@ function methodKeyToName(methodKey) {
|
|
|
44
44
|
function isClassProvider(provider) {
|
|
45
45
|
return typeof provider === 'object' && provider !== null && 'useClass' in provider;
|
|
46
46
|
}
|
|
47
|
+
function isFactoryOrValueProvider(provider) {
|
|
48
|
+
return typeof provider === 'object' && provider !== null && ('useFactory' in provider || 'useValue' in provider);
|
|
49
|
+
}
|
|
50
|
+
function hasEventHandlerMetadata(targetType) {
|
|
51
|
+
return getEventHandlerMetadataEntries(targetType.prototype).length > 0;
|
|
52
|
+
}
|
|
47
53
|
|
|
48
54
|
/**
|
|
49
55
|
* Lifecycle-managed in-process event bus with optional external transport fan-out.
|
|
@@ -68,6 +74,7 @@ class EventBusLifecycleService {
|
|
|
68
74
|
shutdownDrainTimeouts = 0;
|
|
69
75
|
activeDispatches = new Set();
|
|
70
76
|
transport;
|
|
77
|
+
transportClosed = false;
|
|
71
78
|
constructor(runtimeContainer, compiledModules, logger, moduleOptions) {
|
|
72
79
|
this.runtimeContainer = runtimeContainer;
|
|
73
80
|
this.compiledModules = compiledModules;
|
|
@@ -88,19 +95,14 @@ class EventBusLifecycleService {
|
|
|
88
95
|
}
|
|
89
96
|
async onApplicationShutdown() {
|
|
90
97
|
this.lifecycleState = 'stopping';
|
|
98
|
+
let transportClosedCleanly = true;
|
|
91
99
|
if (this.activeDispatches.size > 0) {
|
|
92
100
|
await this.drainActiveDispatches();
|
|
93
101
|
}
|
|
94
102
|
if (this.transport) {
|
|
95
|
-
|
|
96
|
-
await this.transport.close();
|
|
97
|
-
} catch (error) {
|
|
98
|
-
this.transportCloseFailures += 1;
|
|
99
|
-
this.lifecycleState = 'failed';
|
|
100
|
-
this.logger.error('EventBusTransport failed to close.', error, 'EventBusLifecycleService');
|
|
101
|
-
}
|
|
103
|
+
transportClosedCleanly = await this.closeTransportOrRecordFailure('EventBusTransport failed to close.');
|
|
102
104
|
}
|
|
103
|
-
if (
|
|
105
|
+
if (transportClosedCleanly) {
|
|
104
106
|
this.lifecycleState = 'stopped';
|
|
105
107
|
}
|
|
106
108
|
}
|
|
@@ -181,6 +183,14 @@ class EventBusLifecycleService {
|
|
|
181
183
|
this.activeDispatches.delete(dispatchWorkflow);
|
|
182
184
|
}
|
|
183
185
|
}
|
|
186
|
+
trackActiveDispatchWork(dispatchWork) {
|
|
187
|
+
const trackedWork = dispatchWork.then(() => undefined, () => undefined);
|
|
188
|
+
this.activeDispatches.add(trackedWork);
|
|
189
|
+
void trackedWork.finally(() => {
|
|
190
|
+
this.activeDispatches.delete(trackedWork);
|
|
191
|
+
});
|
|
192
|
+
return dispatchWork;
|
|
193
|
+
}
|
|
184
194
|
async awaitShutdownDrain(activePublishes, timeoutMs) {
|
|
185
195
|
let timeoutId;
|
|
186
196
|
const timeout = new Promise(resolve => {
|
|
@@ -215,7 +225,7 @@ class EventBusLifecycleService {
|
|
|
215
225
|
}
|
|
216
226
|
runInvocationTasksInBackground(invocationTasks) {
|
|
217
227
|
for (const task of invocationTasks) {
|
|
218
|
-
void task;
|
|
228
|
+
void this.trackActiveDispatchWork(task);
|
|
219
229
|
}
|
|
220
230
|
}
|
|
221
231
|
async invokeHandlerInBackground(descriptor, event, signal) {
|
|
@@ -257,7 +267,7 @@ class EventBusLifecycleService {
|
|
|
257
267
|
}
|
|
258
268
|
async discoverHandlers() {
|
|
259
269
|
try {
|
|
260
|
-
this.descriptors = this.discoverHandlerDescriptors();
|
|
270
|
+
this.descriptors = await this.discoverHandlerDescriptors();
|
|
261
271
|
this.handlerInstances.clear();
|
|
262
272
|
await this.preloadHandlerInstances(this.descriptors);
|
|
263
273
|
this.discovered = true;
|
|
@@ -311,7 +321,9 @@ class EventBusLifecycleService {
|
|
|
311
321
|
return;
|
|
312
322
|
}
|
|
313
323
|
try {
|
|
314
|
-
|
|
324
|
+
const publishWork = this.transport.publish(channel, payload);
|
|
325
|
+
const trackedPublishWork = this.trackActiveDispatchWork(publishWork);
|
|
326
|
+
await this.awaitInvocationBounds(trackedPublishWork, publishOptions);
|
|
315
327
|
} catch (error) {
|
|
316
328
|
this.transportPublishFailures += 1;
|
|
317
329
|
this.logBoundedTransportPublishError(channel, error);
|
|
@@ -344,9 +356,37 @@ class EventBusLifecycleService {
|
|
|
344
356
|
channelDescriptors.push(descriptor);
|
|
345
357
|
descriptorsByChannel.set(channel, channelDescriptors);
|
|
346
358
|
}
|
|
347
|
-
|
|
348
|
-
|
|
359
|
+
try {
|
|
360
|
+
for (const [channel, channelDescriptors] of descriptorsByChannel) {
|
|
361
|
+
await this.subscribeTransportChannel(channel, channelDescriptors);
|
|
362
|
+
}
|
|
363
|
+
} catch (error) {
|
|
364
|
+
await this.rollbackTransportSubscriptionsAfterBootstrapFailure();
|
|
365
|
+
throw error;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
async rollbackTransportSubscriptionsAfterBootstrapFailure() {
|
|
369
|
+
await this.closeTransportOrRecordFailure('EventBusTransport failed to close after bootstrap subscription failure.');
|
|
370
|
+
}
|
|
371
|
+
async closeTransportOrRecordFailure(message) {
|
|
372
|
+
try {
|
|
373
|
+
await this.closeTransport();
|
|
374
|
+
return true;
|
|
375
|
+
} catch (error) {
|
|
376
|
+
this.transportCloseFailures += 1;
|
|
377
|
+
this.lifecycleState = 'failed';
|
|
378
|
+
this.logger.error(message, error, 'EventBusLifecycleService');
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
async closeTransport() {
|
|
383
|
+
const transport = this.transport;
|
|
384
|
+
if (!transport || this.transportClosed) {
|
|
385
|
+
return;
|
|
349
386
|
}
|
|
387
|
+
await transport.close();
|
|
388
|
+
this.transportClosed = true;
|
|
389
|
+
this.subscribedChannels.clear();
|
|
350
390
|
}
|
|
351
391
|
async subscribeTransportChannel(channel, channelDescriptors) {
|
|
352
392
|
try {
|
|
@@ -391,7 +431,7 @@ class EventBusLifecycleService {
|
|
|
391
431
|
this.logPublishCancelledBeforeDispatch(descriptor);
|
|
392
432
|
return;
|
|
393
433
|
}
|
|
394
|
-
const invocation = this.invokeHandler(descriptor, event);
|
|
434
|
+
const invocation = this.trackActiveDispatchWork(this.invokeHandler(descriptor, event));
|
|
395
435
|
try {
|
|
396
436
|
await this.awaitInvocationBounds(invocation, publishOptions);
|
|
397
437
|
} catch (error) {
|
|
@@ -474,17 +514,17 @@ class EventBusLifecycleService {
|
|
|
474
514
|
})
|
|
475
515
|
};
|
|
476
516
|
}
|
|
477
|
-
discoverHandlerDescriptors() {
|
|
478
|
-
const seen = new
|
|
517
|
+
async discoverHandlerDescriptors() {
|
|
518
|
+
const seen = new Map();
|
|
479
519
|
const descriptors = [];
|
|
480
|
-
for (const candidate of this.discoveryCandidates()) {
|
|
520
|
+
for (const candidate of await this.discoveryCandidates()) {
|
|
481
521
|
const entries = getEventHandlerMetadataEntries(candidate.targetType.prototype);
|
|
482
522
|
if (this.shouldSkipNonSingletonCandidate(candidate, entries.length)) {
|
|
483
523
|
continue;
|
|
484
524
|
}
|
|
485
525
|
for (const entry of entries) {
|
|
486
526
|
const eventType = entry.metadata.eventType;
|
|
487
|
-
if (this.isDuplicateHandlerRegistration(seen, candidate.
|
|
527
|
+
if (this.isDuplicateHandlerRegistration(seen, candidate.token, entry.propertyKey, eventType)) {
|
|
488
528
|
continue;
|
|
489
529
|
}
|
|
490
530
|
descriptors.push(this.createHandlerDescriptor(candidate, entry.propertyKey, eventType));
|
|
@@ -501,11 +541,11 @@ class EventBusLifecycleService {
|
|
|
501
541
|
}
|
|
502
542
|
return true;
|
|
503
543
|
}
|
|
504
|
-
isDuplicateHandlerRegistration(seen,
|
|
505
|
-
let methodsByKey = seen.get(
|
|
544
|
+
isDuplicateHandlerRegistration(seen, token, methodKey, eventType) {
|
|
545
|
+
let methodsByKey = seen.get(token);
|
|
506
546
|
if (!methodsByKey) {
|
|
507
547
|
methodsByKey = new Map();
|
|
508
|
-
seen.set(
|
|
548
|
+
seen.set(token, methodsByKey);
|
|
509
549
|
}
|
|
510
550
|
let seenEventTypes = methodsByKey.get(methodKey);
|
|
511
551
|
if (!seenEventTypes) {
|
|
@@ -528,8 +568,9 @@ class EventBusLifecycleService {
|
|
|
528
568
|
token: candidate.token
|
|
529
569
|
};
|
|
530
570
|
}
|
|
531
|
-
discoveryCandidates() {
|
|
571
|
+
async discoveryCandidates() {
|
|
532
572
|
const candidates = [];
|
|
573
|
+
const providerCandidates = [];
|
|
533
574
|
for (const compiledModule of this.compiledModules) {
|
|
534
575
|
for (const provider of compiledModule.definition.providers ?? []) {
|
|
535
576
|
if (typeof provider === 'function') {
|
|
@@ -548,6 +589,13 @@ class EventBusLifecycleService {
|
|
|
548
589
|
targetType: provider.useClass,
|
|
549
590
|
token: provider.provide
|
|
550
591
|
});
|
|
592
|
+
continue;
|
|
593
|
+
}
|
|
594
|
+
if (isFactoryOrValueProvider(provider)) {
|
|
595
|
+
providerCandidates.push({
|
|
596
|
+
moduleName: compiledModule.type.name,
|
|
597
|
+
provider
|
|
598
|
+
});
|
|
551
599
|
}
|
|
552
600
|
}
|
|
553
601
|
for (const controller of compiledModule.definition.controllers ?? []) {
|
|
@@ -559,13 +607,64 @@ class EventBusLifecycleService {
|
|
|
559
607
|
});
|
|
560
608
|
}
|
|
561
609
|
}
|
|
610
|
+
for (const candidate of providerCandidates) {
|
|
611
|
+
const resolvedCandidate = await this.resolveProviderDiscoveryCandidate(candidate);
|
|
612
|
+
if (resolvedCandidate) {
|
|
613
|
+
candidates.push(resolvedCandidate);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
562
616
|
return candidates;
|
|
563
617
|
}
|
|
618
|
+
resolveProviderDiscoveryCandidate(candidate) {
|
|
619
|
+
const provider = candidate.provider;
|
|
620
|
+
if (!('provide' in provider)) {
|
|
621
|
+
return undefined;
|
|
622
|
+
}
|
|
623
|
+
const scope = scopeFromProvider(provider);
|
|
624
|
+
const token = provider.provide;
|
|
625
|
+
if (scope !== 'singleton') {
|
|
626
|
+
return this.createUnresolvedProviderDiscoveryCandidate(candidate.moduleName, token, scope);
|
|
627
|
+
}
|
|
628
|
+
if ('useValue' in provider) {
|
|
629
|
+
const instance = provider.useValue;
|
|
630
|
+
if (typeof instance !== 'object' || instance === null) {
|
|
631
|
+
return undefined;
|
|
632
|
+
}
|
|
633
|
+
const targetType = instance.constructor;
|
|
634
|
+
if (typeof targetType !== 'function' || !hasEventHandlerMetadata(targetType)) {
|
|
635
|
+
return undefined;
|
|
636
|
+
}
|
|
637
|
+
return {
|
|
638
|
+
moduleName: candidate.moduleName,
|
|
639
|
+
scope,
|
|
640
|
+
targetType,
|
|
641
|
+
token
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
if (typeof token !== 'function' || !hasEventHandlerMetadata(token)) {
|
|
645
|
+
return undefined;
|
|
646
|
+
}
|
|
647
|
+
return {
|
|
648
|
+
moduleName: candidate.moduleName,
|
|
649
|
+
scope,
|
|
650
|
+
targetType: token,
|
|
651
|
+
token
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
createUnresolvedProviderDiscoveryCandidate(moduleName, token, scope) {
|
|
655
|
+
const tokenType = typeof token === 'function' ? token : undefined;
|
|
656
|
+
if (!tokenType) {
|
|
657
|
+
return undefined;
|
|
658
|
+
}
|
|
659
|
+
return {
|
|
660
|
+
moduleName,
|
|
661
|
+
scope,
|
|
662
|
+
targetType: tokenType,
|
|
663
|
+
token
|
|
664
|
+
};
|
|
665
|
+
}
|
|
564
666
|
async invokeHandler(descriptor, event) {
|
|
565
667
|
const instance = await this.resolveHandlerInstance(descriptor);
|
|
566
|
-
if (instance === undefined) {
|
|
567
|
-
return;
|
|
568
|
-
}
|
|
569
668
|
const value = instance[descriptor.methodKey];
|
|
570
669
|
if (typeof value !== 'function') {
|
|
571
670
|
this.logger.warn(`Event handler ${descriptor.targetName}.${descriptor.methodName} is not callable and was skipped.`, 'EventBusLifecycleService');
|
|
@@ -589,7 +688,7 @@ class EventBusLifecycleService {
|
|
|
589
688
|
} catch (error) {
|
|
590
689
|
this.handlerInstances.delete(descriptor.token);
|
|
591
690
|
this.logger.error(`Failed to resolve event handler target ${descriptor.targetName} from module ${descriptor.moduleName}.`, error, 'EventBusLifecycleService');
|
|
592
|
-
|
|
691
|
+
throw error;
|
|
593
692
|
}
|
|
594
693
|
}
|
|
595
694
|
static {
|
package/dist/types.d.ts
CHANGED
|
@@ -27,7 +27,8 @@ export interface EventPublishOptions {
|
|
|
27
27
|
export interface EventBusTransport {
|
|
28
28
|
/**
|
|
29
29
|
* Publish an event payload to the external transport under the given channel name.
|
|
30
|
-
* Called
|
|
30
|
+
* Called for each selected transport channel when a transport is configured; one local
|
|
31
|
+
* `publish()` invocation can fan out to multiple inherited event channels.
|
|
31
32
|
*/
|
|
32
33
|
publish(channel: string, payload: unknown): Promise<void>;
|
|
33
34
|
/**
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE/D,qGAAqG;AACrG,MAAM,WAAW,SAAS,CAAC,MAAM,SAAS,MAAM,GAAG,MAAM;IACvD,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,0CAA0C;AAC1C,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,kEAAkE;AAClE,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,mBAAmB,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;CACd;AAED,8EAA8E;AAC9E,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,kGAAkG;AAClG,MAAM,WAAW,iBAAiB;IAChC
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE/D,qGAAqG;AACrG,MAAM,WAAW,SAAS,CAAC,MAAM,SAAS,MAAM,GAAG,MAAM;IACvD,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,0CAA0C;AAC1C,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,kEAAkE;AAClE,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,mBAAmB,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;CACd;AAED,8EAA8E;AAC9E,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,kGAAkG;AAClG,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1D;;;;OAIG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExF;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,sFAAsF;AACtF,MAAM,WAAW,qBAAqB;IACpC,kFAAkF;IAClF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,eAAe,CAAC,EAAE,OAAO,CAAC;KAC3B,CAAC;IACF,kEAAkE;IAClE,QAAQ,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;IACF;;;;OAIG;IACH,SAAS,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED,+DAA+D;AAC/D,MAAM,WAAW,QAAQ;IACvB;;;;;;OAMG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtE"}
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"pubsub",
|
|
9
9
|
"in-process"
|
|
10
10
|
],
|
|
11
|
-
"version": "
|
|
11
|
+
"version": "2.0.0",
|
|
12
12
|
"private": false,
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"repository": {
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
"dist"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@fluojs/core": "^1.
|
|
43
|
-
"@fluojs/di": "^
|
|
44
|
-
"@fluojs/runtime": "^
|
|
42
|
+
"@fluojs/core": "^1.1.0",
|
|
43
|
+
"@fluojs/di": "^2.0.0",
|
|
44
|
+
"@fluojs/runtime": "^2.0.1"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"ioredis": "^5.0.0"
|