You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: packages/core/README.md
+61-42Lines changed: 61 additions & 42 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,12 +3,12 @@
3
3
The `InboxOutboxModule` is solution designed for NestJS to tackle the challenges of dual write and reliable event delivery in distributed systems. It addresses scenarios where one module emits an integration event, and another module must receive and process this information to maintain system-wide data consistency, which is not possible with a in-memory event bus.
@@ -18,102 +18,99 @@ The `InboxOutboxModule` is solution designed for NestJS to tackle the challenges
18
18
19
19
3.**Cross-Module Consistency**: Facilitates keeping data consistent across different modules or microservices by ensuring that all relevant parts of the system are updated based on emitted events.
> **Note:** You should only group events that are related to each other (By case and data) in the same listener. If you have events that are not related to each other, you should create a separate listener for each event.
95
93
96
94
### Event Emission
97
95
98
-
99
96
The module uses a `TransactionalEventEmitter` for reliable event emission. This component is designed to work similarly to eventemitter2, but with added transactional capabilities.
100
97
101
-
102
98
1.**Transactional Emission:** The `TransactionalEventEmitter` takes two arguments:
99
+
103
100
- The event to be emitted
104
101
- An array of entities to be saved or removed in the transaction
105
102
106
103
2.**Immediate Delivery Attempt:** Upon emission, the system immediately tries to deliver the event to registered listeners.
107
104
108
105
3.**Fallback Mechanism:** If immediate delivery fails (due to network issues, service unavailability, etc.), a built-in polling mechanism ensures eventual delivery.
109
106
107
+
#### By doing that we are achieving the following:
110
108
111
-
#### By doing that we are achieving the following:
112
109
- Events are only emitted if the associated database transaction succeeds.
113
110
- Even if immediate delivery fails, the event will eventually be processed.
114
111
112
+
-**Emitting an Event:** To emit an event, use the `emit` method of the `transactionalEventEmitter`, providing the event object and associated transactional entities. _Operation has to be awaited._
115
113
116
-
-**Emitting an Event:** To emit an event, use the `emit` method of the `transactionalEventEmitter`, providing the event object and associated transactional entities. *Operation has to be awaited.*
@@ -133,6 +130,7 @@ The module uses a `TransactionalEventEmitter` for reliable event emission. This
133
130
The `TransactionalEventEmitter` provides two methods for emitting events:
134
131
135
132
-**emit:**
133
+
136
134
- Fires the event and attempts immediate delivery to listeners, but does **not** wait for listeners to finish execution.
137
135
- Use this when you want to trigger event delivery and continue your logic without waiting for listeners to complete.
138
136
@@ -141,32 +139,42 @@ The `TransactionalEventEmitter` provides two methods for emitting events:
141
139
- Use this when you need to ensure that all listeners have processed the event before proceeding (e.g., for transactional workflows or when listener side effects are required before continuing).
142
140
143
141
**Example:**
142
+
144
143
```typescript
145
144
// Wait for all listeners to finish processing the event
> **Note:** Use `emitAsync` if you need to wait for listeners to execute and complete before moving on. Use `emit` if you want to fire-and-forget the event delivery.
156
161
157
162
### Event Contract:
163
+
158
164
Ensure that your event classes implement the `InboxOutboxEvent` interface for consistency and clarity.
159
165
160
166
### Module Registration
161
167
162
168
#### Options for Registration
169
+
163
170
-**expiresAtTTL**: This is how long the event will be stored in the database and will be retried
164
171
-**maxExecutionTimeTTL**: This is how long it will wait for the listener to process the event, if it takes longer than this, it will be retried
165
172
-**readyToRetryAfterTTL**: This is how long it will wait before retrying the event listeners
166
173
-**retryEveryMilliseconds**: This is how often it will check for events that need to be retried
167
174
-**maxInboxOutboxTransportEventPerRetry**: This is how many events it will retry at a time
168
175
169
176
#### Registration
177
+
170
178
- Register the `InboxOutboxModule` within your application's bootstrap process, specifying global accessibility and event configurations.
171
179
```typescript
172
180
InboxOutboxModule.registerAsync({
@@ -182,65 +190,76 @@ Ensure that your event classes implement the `InboxOutboxEvent` interface for co
To extend the InboxOutboxModule with support for additional ORMs or databases, you can create a new driver. Follow these steps to implement and integrate your custom driver:
207
216
208
217
### 1. Fork the Repository
218
+
209
219
Begin by forking the main InboxOutboxModule repository to your own GitHub account.
210
220
211
221
### 2. Create a New Package
222
+
212
223
Use Lerna to create a new package in the `packages` folder:
224
+
213
225
```bash
214
226
lerna create @nestixis/your-orm-driver
215
227
```
228
+
216
229
Alternatively, you can copy an existing driver package and modify it.
217
230
218
231
### 3. Implement the DatabaseDriver Interface
232
+
219
233
Develop your driver by implementing the `DatabaseDriver` interface. Pay special attention to:
234
+
220
235
- Transaction handling
221
236
- Pessimistic locking mechanisms
222
237
- Persist and flush operations
223
238
224
239
These aspects are crucial for maintaining data consistency and performance.
225
240
226
241
### 4. Implement the DatabaseDriverFactory Interface
242
+
227
243
Create a factory class that implements the `DatabaseDriverFactory` interface. This factory will be responsible for instantiating your custom driver.
228
244
229
245
### 5. Create a Persistable Model
246
+
230
247
Create a model that can be persisted in your target database. This model shall implement the `InboxOutboxTransportEvent` interface.
231
248
232
249
### 6. Develop a Proof of Concept
250
+
233
251
Create a demo application that utilizes your new driver. This PoC will serve as both a testing ground and an example for other developers.
234
252
235
253
### 7. Contribute or Publish
254
+
236
255
You have two options for making your driver available:
256
+
237
257
- Create a Pull Request to the main InboxOutboxModule repository for inclusion in the official release.
238
258
- Publish your driver to npm under your own namespace.
239
259
240
260
### Best Practices
261
+
241
262
- Ensure comprehensive test coverage for your driver.
242
263
- Document any database-specific considerations or configurations.
243
264
- Follow the coding standards and conventions established in the existing drivers.
244
265
- Consider performance implications, especially for high-throughput systems.
0 commit comments