@etohq/event-bus-redis 1.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.md +79 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/initialize/index.d.ts +4 -0
- package/dist/initialize/index.d.ts.map +1 -0
- package/dist/initialize/index.js +16 -0
- package/dist/initialize/index.js.map +1 -0
- package/dist/loaders/index.d.ts +4 -0
- package/dist/loaders/index.d.ts.map +1 -0
- package/dist/loaders/index.js +35 -0
- package/dist/loaders/index.js.map +1 -0
- package/dist/services/event-bus-redis.d.ts +47 -0
- package/dist/services/event-bus-redis.d.ts.map +1 -0
- package/dist/services/event-bus-redis.js +214 -0
- package/dist/services/event-bus-redis.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/index.d.ts +39 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://www.etohq.com">
|
|
3
|
+
<img alt="Eto" src="https://user-images.githubusercontent.com/7554214/153162406-bf8fd16f-aa98-4604-b87b-e13ab4baf604.png" width="100" />
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
6
|
+
<h1 align="center">
|
|
7
|
+
@etohq/event-bus-redis
|
|
8
|
+
</h1>
|
|
9
|
+
|
|
10
|
+
<h4 align="center">
|
|
11
|
+
<a href="https://docs.etohq.com">Documentation</a> |
|
|
12
|
+
<a href="https://www.etohq.com">Website</a>
|
|
13
|
+
</h4>
|
|
14
|
+
|
|
15
|
+
<p align="center">
|
|
16
|
+
An open source composable commerce engine built for developers.
|
|
17
|
+
</p>
|
|
18
|
+
<p align="center">
|
|
19
|
+
<a href="https://github.com/etohq/eto/blob/master/LICENSE">
|
|
20
|
+
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="Eto is released under the MIT license." />
|
|
21
|
+
</a>
|
|
22
|
+
<a href="https://circleci.com/gh/etohq/eto">
|
|
23
|
+
<img src="https://circleci.com/gh/etohq/eto.svg?style=shield" alt="Current CircleCI build status." />
|
|
24
|
+
</a>
|
|
25
|
+
<a href="https://github.com/etohq/eto/blob/master/CONTRIBUTING.md">
|
|
26
|
+
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat" alt="PRs welcome!" />
|
|
27
|
+
</a>
|
|
28
|
+
<a href="https://www.producthunt.com/posts/eto"><img src="https://img.shields.io/badge/Product%20Hunt-%231%20Product%20of%20the%20Day-%23DA552E" alt="Product Hunt"></a>
|
|
29
|
+
<a href="https://discord.gg/xpCwq3Kfn8">
|
|
30
|
+
<img src="https://img.shields.io/badge/chat-on%20discord-7289DA.svg" alt="Discord Chat" />
|
|
31
|
+
</a>
|
|
32
|
+
<a href="https://twitter.com/intent/follow?screen_name=etohq">
|
|
33
|
+
<img src="https://img.shields.io/twitter/follow/etohq.svg?label=Follow%20@etohq" alt="Follow @etohq" />
|
|
34
|
+
</a>
|
|
35
|
+
</p>
|
|
36
|
+
|
|
37
|
+
## Overview
|
|
38
|
+
|
|
39
|
+
Redis Event Bus module for Eto. When installed, the events system of Eto is powered by BullMQ and `io-redis`. BullMQ is responsible for the message queue and worker. `io-redis` is the underlying Redis client, that BullMQ connects to for events storage.
|
|
40
|
+
|
|
41
|
+
## Getting started
|
|
42
|
+
|
|
43
|
+
Install the module:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
yarn add @etohq/event-bus-redis
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Add the module to your `eto-config.js`:
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
module.exports = {
|
|
53
|
+
// ...
|
|
54
|
+
modules: [
|
|
55
|
+
{
|
|
56
|
+
resolve: "@etohq/event-bus-redis",
|
|
57
|
+
options: {
|
|
58
|
+
redisUrl: "redis:..",
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
// ...
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Configuration
|
|
67
|
+
|
|
68
|
+
The module can be configured with the following options:
|
|
69
|
+
|
|
70
|
+
| Option | Type | Description | Default |
|
|
71
|
+
| -------------- | --------- | ------------------------------------------------------------------------------------------------------------------------ | --------------- |
|
|
72
|
+
| `redisUrl` | `string` | URL of the Redis instance to connect to. | `events-worker` |
|
|
73
|
+
| `queueName` | `string?` | Name of the BullMQ queue. | `events-queue` |
|
|
74
|
+
| `queueOptions` | `object?` | Options for the BullMQ queue. See BullMQ's [documentation](https://api.docs.bullmq.io/interfaces/QueueOptions.html). | `{}` |
|
|
75
|
+
| `redisOptions` | `object?` | Options for the Redis instance. See `io-redis`'s [documentation](https://luin.github.io/ioredis/index.html#RedisOptions) | `{}` |
|
|
76
|
+
|
|
77
|
+
**Info**: See how the options are applied in the [RedisEventBusService](https://github.com/etohq/eto/blob/0c1d1d590463fa30b083c4312293348bdf6596be/packages/event-bus-redis/src/services/event-bus-redis.ts#L52) and [loader](https://github.com/etohq/eto/blob/0c1d1d590463fa30b083c4312293348bdf6596be/packages/event-bus-redis/src/loaders/index.ts).
|
|
78
|
+
|
|
79
|
+
If you do not provide a `redisUrl` in the module options, the server will fail to start.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAOtD,QAAA,MAAM,gBAAgB,EAAE,aAGvB,CAAA;AAED,eAAe,gBAAgB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
const loaders_1 = __importDefault(require("./loaders"));
|
|
21
|
+
const event_bus_redis_1 = __importDefault(require("./services/event-bus-redis"));
|
|
22
|
+
const service = event_bus_redis_1.default;
|
|
23
|
+
const loaders = [loaders_1.default];
|
|
24
|
+
const moduleDefinition = {
|
|
25
|
+
service,
|
|
26
|
+
loaders,
|
|
27
|
+
};
|
|
28
|
+
exports.default = moduleDefinition;
|
|
29
|
+
__exportStar(require("./initialize"), exports);
|
|
30
|
+
__exportStar(require("./types"), exports);
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AACA,wDAA8B;AAC9B,iFAA6D;AAE7D,MAAM,OAAO,GAAG,yBAAoB,CAAA;AACpC,MAAM,OAAO,GAAG,CAAC,iBAAM,CAAC,CAAA;AAExB,MAAM,gBAAgB,GAAkB;IACtC,OAAO;IACP,OAAO;CACR,CAAA;AAED,kBAAe,gBAAgB,CAAA;AAC/B,+CAA4B;AAC5B,0CAAuB"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ExternalModuleDeclaration, IEventBusService } from "@etohq/framework/types";
|
|
2
|
+
import { EventBusRedisModuleOptions } from "../types";
|
|
3
|
+
export declare const initialize: (options?: EventBusRedisModuleOptions | ExternalModuleDeclaration) => Promise<IEventBusService>;
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/initialize/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAEjB,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAA;AAErD,eAAO,MAAM,UAAU,aACX,0BAA0B,GAAG,yBAAyB,KAC/D,OAAO,CAAC,gBAAgB,CAW1B,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.initialize = void 0;
|
|
4
|
+
const modules_sdk_1 = require("@etohq/framework/modules-sdk");
|
|
5
|
+
const utils_1 = require("@etohq/framework/utils");
|
|
6
|
+
const initialize = async (options) => {
|
|
7
|
+
const serviceKey = utils_1.Modules.EVENT_BUS;
|
|
8
|
+
const loaded = await modules_sdk_1.EtoModule.bootstrap({
|
|
9
|
+
moduleKey: serviceKey,
|
|
10
|
+
defaultPath: "@etohq/event-bus-redis",
|
|
11
|
+
declaration: options,
|
|
12
|
+
});
|
|
13
|
+
return loaded[serviceKey];
|
|
14
|
+
};
|
|
15
|
+
exports.initialize = initialize;
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/initialize/index.ts"],"names":[],"mappings":";;;AAAA,8DAAwD;AAMxD,kDAAgD;AAGzC,MAAM,UAAU,GAAG,KAAK,EAC7B,OAAgE,EACrC,EAAE;IAC7B,MAAM,UAAU,GAAG,eAAO,CAAC,SAAS,CAAA;IACpC,MAAM,MAAM,GAAG,MAAM,uBAAS,CAAC,SAAS,CAAmB;QACzD,SAAS,EAAE,UAAU;QACrB,WAAW,EAAE,wBAAwB;QACrC,WAAW,EAAE,OAEgB;KAC9B,CAAC,CAAA;IAEF,OAAO,MAAM,CAAC,UAAU,CAAC,CAAA;AAC3B,CAAC,CAAA;AAbY,QAAA,UAAU,cAatB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/loaders/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;0DAUnD,aAAa,KAAG,OAAO,CAAC,IAAI,CAAC;AAJhC,wBAoCC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const awilix_1 = require("awilix");
|
|
7
|
+
const ioredis_1 = __importDefault(require("ioredis"));
|
|
8
|
+
const os_1 = require("os");
|
|
9
|
+
exports.default = async ({ container, logger, options, }) => {
|
|
10
|
+
const { redisUrl, redisOptions } = options;
|
|
11
|
+
if (!redisUrl) {
|
|
12
|
+
throw Error("No `redisUrl` provided in project config. It is required for the Redis Event Bus.");
|
|
13
|
+
}
|
|
14
|
+
const connection = new ioredis_1.default(redisUrl, {
|
|
15
|
+
// Required config. See: https://github.com/OptimalBits/bull/blob/develop/CHANGELOG.md#breaking-changes
|
|
16
|
+
maxRetriesPerRequest: null,
|
|
17
|
+
enableReadyCheck: false,
|
|
18
|
+
// Lazy connect to properly handle connection errors
|
|
19
|
+
lazyConnect: true,
|
|
20
|
+
...(redisOptions ?? {}),
|
|
21
|
+
});
|
|
22
|
+
try {
|
|
23
|
+
await new Promise(async (resolve) => {
|
|
24
|
+
await connection.connect(resolve);
|
|
25
|
+
});
|
|
26
|
+
logger?.info(`Connection to Redis in module 'event-bus-redis' established`);
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
logger?.error(`An error occurred while connecting to Redis in module 'event-bus-redis':${os_1.EOL} ${err}`);
|
|
30
|
+
}
|
|
31
|
+
container.register({
|
|
32
|
+
eventBusRedisConnection: (0, awilix_1.asValue)(connection),
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/loaders/index.ts"],"names":[],"mappings":";;;;;AACA,mCAAgC;AAChC,sDAA2B;AAC3B,2BAAwB;AAGxB,kBAAe,KAAK,EAAE,EACpB,SAAS,EACT,MAAM,EACN,OAAO,GACO,EAAiB,EAAE;IACjC,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,OAAqC,CAAA;IAExE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,KAAK,CACT,mFAAmF,CACpF,CAAA;IACH,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,iBAAK,CAAC,QAAQ,EAAE;QACrC,uGAAuG;QACvG,oBAAoB,EAAE,IAAI;QAC1B,gBAAgB,EAAE,KAAK;QACvB,oDAAoD;QACpD,WAAW,EAAE,IAAI;QACjB,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC;KACxB,CAAC,CAAA;IAEF,IAAI,CAAC;QACH,MAAM,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAClC,MAAM,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QACnC,CAAC,CAAC,CAAA;QACF,MAAM,EAAE,IAAI,CAAC,6DAA6D,CAAC,CAAA;IAC7E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,EAAE,KAAK,CACX,2EAA2E,QAAG,IAAI,GAAG,EAAE,CACxF,CAAA;IACH,CAAC;IAED,SAAS,CAAC,QAAQ,CAAC;QACjB,uBAAuB,EAAE,IAAA,gBAAO,EAAC,UAAU,CAAC;KAC7C,CAAC,CAAA;AACJ,CAAC,CAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { InternalModuleDeclaration, Logger, Message } from "@etohq/framework/types";
|
|
2
|
+
import { AbstractEventBusModuleService } from "@etohq/framework/utils";
|
|
3
|
+
import { Queue, Worker } from "bullmq";
|
|
4
|
+
import { Redis } from "ioredis";
|
|
5
|
+
import { BullJob, EventBusRedisModuleOptions, Options } from "../types";
|
|
6
|
+
type InjectedDependencies = {
|
|
7
|
+
logger: Logger;
|
|
8
|
+
eventBusRedisConnection: Redis;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Can keep track of multiple subscribers to different events and run the
|
|
12
|
+
* subscribers when events happen. Events will run asynchronously.
|
|
13
|
+
*/
|
|
14
|
+
export default class RedisEventBusService extends AbstractEventBusModuleService {
|
|
15
|
+
protected readonly logger_: Logger;
|
|
16
|
+
protected readonly moduleOptions_: EventBusRedisModuleOptions;
|
|
17
|
+
protected readonly moduleDeclaration_: InternalModuleDeclaration;
|
|
18
|
+
protected readonly eventBusRedisConnection_: Redis;
|
|
19
|
+
protected queue_: Queue;
|
|
20
|
+
protected bullWorker_: Worker;
|
|
21
|
+
constructor({ logger, eventBusRedisConnection }: InjectedDependencies, moduleOptions: EventBusRedisModuleOptions | undefined, moduleDeclaration: InternalModuleDeclaration);
|
|
22
|
+
__hooks: {
|
|
23
|
+
onApplicationStart: () => Promise<void>;
|
|
24
|
+
onApplicationShutdown: () => Promise<void>;
|
|
25
|
+
onApplicationPrepareShutdown: () => Promise<void>;
|
|
26
|
+
};
|
|
27
|
+
private buildEvents;
|
|
28
|
+
/**
|
|
29
|
+
* Emit a single or number of events
|
|
30
|
+
* @param eventsData
|
|
31
|
+
* @param options
|
|
32
|
+
*/
|
|
33
|
+
emit<T = unknown>(eventsData: Message<T> | Message<T>[], options?: Options): Promise<void>;
|
|
34
|
+
private setExpire;
|
|
35
|
+
private groupEvents;
|
|
36
|
+
private getGroupedEvents;
|
|
37
|
+
releaseGroupedEvents(eventGroupId: string): Promise<void>;
|
|
38
|
+
clearGroupedEvents(eventGroupId: string): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Handles incoming jobs.
|
|
41
|
+
* @param job The job object
|
|
42
|
+
* @return resolves to the results of the subscriber calls.
|
|
43
|
+
*/
|
|
44
|
+
worker_: <T>(job: BullJob<T>) => Promise<unknown>;
|
|
45
|
+
}
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=event-bus-redis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-bus-redis.d.ts","sourceRoot":"","sources":["../../src/services/event-bus-redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,yBAAyB,EACzB,MAAM,EACN,OAAO,EACR,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,6BAA6B,EAG9B,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAkB,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,OAAO,EAAE,0BAA0B,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAEvE,KAAK,oBAAoB,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,uBAAuB,EAAE,KAAK,CAAA;CAC/B,CAAA;AAQD;;;GAGG;AAEH,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,6BAA6B;IAC7E,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IAClC,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,0BAA0B,CAAA;IAE7D,SAAS,CAAC,QAAQ,CAAC,kBAAkB,EAAE,yBAAyB,CAAA;IAChE,SAAS,CAAC,QAAQ,CAAC,wBAAwB,EAAE,KAAK,CAAA;IAElD,SAAS,CAAC,MAAM,EAAE,KAAK,CAAA;IACvB,SAAS,CAAC,WAAW,EAAE,MAAM,CAAA;gBAG3B,EAAE,MAAM,EAAE,uBAAuB,EAAE,EAAE,oBAAoB,EACzD,aAAa,EAAE,0BAA0B,YAAK,EAC9C,iBAAiB,EAAE,yBAAyB;IAgC9C,OAAO;;;;MAYN;IAED,OAAO,CAAC,WAAW;IAmCnB;;;;OAIG;IACG,IAAI,CAAC,CAAC,GAAG,OAAO,EACpB,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,EACrC,OAAO,GAAE,OAAY,GACpB,OAAO,CAAC,IAAI,CAAC;YAmDF,SAAS;YAQT,WAAW;YAUX,gBAAgB;IAUxB,oBAAoB,CAAC,YAAY,EAAE,MAAM;IAQzC,kBAAkB,CAAC,YAAY,EAAE,MAAM;IAQ7C;;;;OAIG;IACH,OAAO,GAAU,CAAC,OAAO,OAAO,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,OAAO,CAAC,CAoGrD;CACF"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("@etohq/framework/utils");
|
|
4
|
+
const bullmq_1 = require("bullmq");
|
|
5
|
+
/**
|
|
6
|
+
* Can keep track of multiple subscribers to different events and run the
|
|
7
|
+
* subscribers when events happen. Events will run asynchronously.
|
|
8
|
+
*/
|
|
9
|
+
// eslint-disable-next-line max-len
|
|
10
|
+
class RedisEventBusService extends utils_1.AbstractEventBusModuleService {
|
|
11
|
+
constructor({ logger, eventBusRedisConnection }, moduleOptions = {}, moduleDeclaration) {
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
// eslint-disable-next-line prefer-rest-params
|
|
14
|
+
super(...arguments);
|
|
15
|
+
this.__hooks = {
|
|
16
|
+
onApplicationStart: async () => {
|
|
17
|
+
await this.bullWorker_?.run();
|
|
18
|
+
},
|
|
19
|
+
onApplicationShutdown: async () => {
|
|
20
|
+
await this.queue_.close();
|
|
21
|
+
// eslint-disable-next-line max-len
|
|
22
|
+
this.eventBusRedisConnection_.disconnect();
|
|
23
|
+
},
|
|
24
|
+
onApplicationPrepareShutdown: async () => {
|
|
25
|
+
await this.bullWorker_?.close();
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Handles incoming jobs.
|
|
30
|
+
* @param job The job object
|
|
31
|
+
* @return resolves to the results of the subscriber calls.
|
|
32
|
+
*/
|
|
33
|
+
this.worker_ = async (job) => {
|
|
34
|
+
const { data, name, opts } = job;
|
|
35
|
+
const eventSubscribers = this.eventToSubscribersMap.get(name) || [];
|
|
36
|
+
const wildcardSubscribers = this.eventToSubscribersMap.get("*") || [];
|
|
37
|
+
const allSubscribers = eventSubscribers.concat(wildcardSubscribers);
|
|
38
|
+
// Pull already completed subscribers from the job data
|
|
39
|
+
const completedSubscribers = job.data.completedSubscriberIds || [];
|
|
40
|
+
// Filter out already completed subscribers from the all subscribers
|
|
41
|
+
const subscribersInCurrentAttempt = allSubscribers.filter((subscriber) => subscriber.id && !completedSubscribers.includes(subscriber.id));
|
|
42
|
+
const currentAttempt = job.attemptsMade;
|
|
43
|
+
const isRetry = currentAttempt > 1;
|
|
44
|
+
const configuredAttempts = job.opts.attempts;
|
|
45
|
+
const isFinalAttempt = currentAttempt === configuredAttempts;
|
|
46
|
+
if (!opts.internal) {
|
|
47
|
+
if (isRetry) {
|
|
48
|
+
if (isFinalAttempt) {
|
|
49
|
+
this.logger_.info(`Final retry attempt for ${name}`);
|
|
50
|
+
}
|
|
51
|
+
this.logger_.info(`Retrying ${name} which has ${eventSubscribers.length} subscribers (${subscribersInCurrentAttempt.length} of them failed)`);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
this.logger_.info(`Processing ${name} which has ${eventSubscribers.length} subscribers`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const completedSubscribersInCurrentAttempt = [];
|
|
58
|
+
const subscribersResult = await Promise.all(subscribersInCurrentAttempt.map(async ({ id, subscriber }) => {
|
|
59
|
+
// De-serialize the event data and metadata from a single field into the original format expected by the subscribers
|
|
60
|
+
const event = {
|
|
61
|
+
name,
|
|
62
|
+
data: data.data,
|
|
63
|
+
metadata: data.metadata,
|
|
64
|
+
};
|
|
65
|
+
try {
|
|
66
|
+
return await subscriber(event).then((data) => {
|
|
67
|
+
// For every subscriber that completes successfully, add their id to the list of completed subscribers
|
|
68
|
+
completedSubscribersInCurrentAttempt.push(id);
|
|
69
|
+
return data;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
this.logger_?.warn(`An error occurred while processing ${name}:`);
|
|
74
|
+
this.logger_?.warn(err);
|
|
75
|
+
return err;
|
|
76
|
+
}
|
|
77
|
+
}));
|
|
78
|
+
// If the number of completed subscribers is different from the number of subcribers to process in current attempt, some of them failed
|
|
79
|
+
const didSubscribersFail = completedSubscribersInCurrentAttempt.length !==
|
|
80
|
+
subscribersInCurrentAttempt.length;
|
|
81
|
+
const isRetriesConfigured = configuredAttempts > 1;
|
|
82
|
+
// Therefore, if retrying is configured, we try again
|
|
83
|
+
const shouldRetry = didSubscribersFail && isRetriesConfigured && !isFinalAttempt;
|
|
84
|
+
if (shouldRetry) {
|
|
85
|
+
const updatedCompletedSubscribers = [
|
|
86
|
+
...completedSubscribers,
|
|
87
|
+
...completedSubscribersInCurrentAttempt,
|
|
88
|
+
];
|
|
89
|
+
job.data.completedSubscriberIds = updatedCompletedSubscribers;
|
|
90
|
+
await job.updateData(job.data);
|
|
91
|
+
const errorMessage = `One or more subscribers of ${name} failed. Retrying...`;
|
|
92
|
+
this.logger_.warn(errorMessage);
|
|
93
|
+
throw Error(errorMessage);
|
|
94
|
+
}
|
|
95
|
+
if (didSubscribersFail && !isFinalAttempt) {
|
|
96
|
+
// If retrying is not configured, we log a warning to allow server admins to recover manually
|
|
97
|
+
this.logger_.warn(`One or more subscribers of ${name} failed. Retrying is not configured. Use 'attempts' option when emitting events.`);
|
|
98
|
+
}
|
|
99
|
+
return subscribersResult;
|
|
100
|
+
};
|
|
101
|
+
this.eventBusRedisConnection_ = eventBusRedisConnection;
|
|
102
|
+
this.moduleOptions_ = moduleOptions;
|
|
103
|
+
this.logger_ = logger;
|
|
104
|
+
this.queue_ = new bullmq_1.Queue(moduleOptions.queueName ?? `events-queue`, {
|
|
105
|
+
prefix: `${this.constructor.name}`,
|
|
106
|
+
...(moduleOptions.queueOptions ?? {}),
|
|
107
|
+
connection: eventBusRedisConnection,
|
|
108
|
+
});
|
|
109
|
+
// Register our worker to handle emit calls
|
|
110
|
+
if (this.isWorkerMode) {
|
|
111
|
+
this.bullWorker_ = new bullmq_1.Worker(moduleOptions.queueName ?? "events-queue", this.worker_, {
|
|
112
|
+
prefix: `${this.constructor.name}`,
|
|
113
|
+
...(moduleOptions.workerOptions ?? {}),
|
|
114
|
+
connection: eventBusRedisConnection,
|
|
115
|
+
autorun: false,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
buildEvents(eventsData, options = {}) {
|
|
120
|
+
const opts = {
|
|
121
|
+
// default options
|
|
122
|
+
removeOnComplete: true,
|
|
123
|
+
attempts: 1,
|
|
124
|
+
// global options
|
|
125
|
+
...(this.moduleOptions_.jobOptions ?? {}),
|
|
126
|
+
...options,
|
|
127
|
+
};
|
|
128
|
+
return eventsData.map((eventData) => {
|
|
129
|
+
// We want to preserve event data + metadata. However, bullmq only allows for a single data field.
|
|
130
|
+
// Therefore, upon adding jobs to the queue we will serialize the event data and metadata into a single field
|
|
131
|
+
// and upon processing the job, we will deserialize it back into the original format expected by the subscribers.
|
|
132
|
+
const event = {
|
|
133
|
+
data: eventData.data,
|
|
134
|
+
metadata: eventData.metadata,
|
|
135
|
+
};
|
|
136
|
+
return {
|
|
137
|
+
data: event,
|
|
138
|
+
name: eventData.name,
|
|
139
|
+
opts: {
|
|
140
|
+
// options for event group
|
|
141
|
+
...opts,
|
|
142
|
+
// options for a particular event
|
|
143
|
+
...eventData.options,
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Emit a single or number of events
|
|
150
|
+
* @param eventsData
|
|
151
|
+
* @param options
|
|
152
|
+
*/
|
|
153
|
+
async emit(eventsData, options = {}) {
|
|
154
|
+
let eventsDataArray = Array.isArray(eventsData) ? eventsData : [eventsData];
|
|
155
|
+
const { groupedEventsTTL = 600 } = options;
|
|
156
|
+
delete options.groupedEventsTTL;
|
|
157
|
+
const eventsToEmit = eventsDataArray.filter((eventData) => !(0, utils_1.isPresent)(eventData.metadata?.eventGroupId));
|
|
158
|
+
const eventsToGroup = eventsDataArray.filter((eventData) => (0, utils_1.isPresent)(eventData.metadata?.eventGroupId));
|
|
159
|
+
const groupEventsMap = new Map();
|
|
160
|
+
for (const event of eventsToGroup) {
|
|
161
|
+
const groupId = event.metadata?.eventGroupId;
|
|
162
|
+
const groupEvents = groupEventsMap.get(groupId) ?? [];
|
|
163
|
+
groupEvents.push(event);
|
|
164
|
+
groupEventsMap.set(groupId, groupEvents);
|
|
165
|
+
}
|
|
166
|
+
const promises = [];
|
|
167
|
+
if (eventsToEmit.length) {
|
|
168
|
+
const emitData = this.buildEvents(eventsToEmit, options);
|
|
169
|
+
promises.push(this.queue_.addBulk(emitData));
|
|
170
|
+
}
|
|
171
|
+
for (const [groupId, events] of groupEventsMap.entries()) {
|
|
172
|
+
if (!events?.length) {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
// Set a TTL for the key of the list that is scoped to a group
|
|
176
|
+
// This will be helpful in preventing stale data from staying in redis for too long
|
|
177
|
+
// in the event the module fails to cleanup events. For long running workflows, setting a much higher
|
|
178
|
+
// TTL or even skipping the TTL would be required
|
|
179
|
+
void this.setExpire(groupId, groupedEventsTTL);
|
|
180
|
+
const eventsData = this.buildEvents(events, options);
|
|
181
|
+
promises.push(this.groupEvents(groupId, eventsData));
|
|
182
|
+
}
|
|
183
|
+
await (0, utils_1.promiseAll)(promises);
|
|
184
|
+
}
|
|
185
|
+
async setExpire(eventGroupId, ttl) {
|
|
186
|
+
if (!eventGroupId) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
await this.eventBusRedisConnection_.expire(`staging:${eventGroupId}`, ttl);
|
|
190
|
+
}
|
|
191
|
+
async groupEvents(eventGroupId, events) {
|
|
192
|
+
await this.eventBusRedisConnection_.rpush(`staging:${eventGroupId}`, ...events.map((event) => JSON.stringify(event)));
|
|
193
|
+
}
|
|
194
|
+
async getGroupedEvents(eventGroupId) {
|
|
195
|
+
return await this.eventBusRedisConnection_
|
|
196
|
+
.lrange(`staging:${eventGroupId}`, 0, -1)
|
|
197
|
+
.then((result) => {
|
|
198
|
+
return result.map((jsonString) => JSON.parse(jsonString));
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
async releaseGroupedEvents(eventGroupId) {
|
|
202
|
+
const groupedEvents = await this.getGroupedEvents(eventGroupId);
|
|
203
|
+
await this.queue_.addBulk(groupedEvents);
|
|
204
|
+
await this.clearGroupedEvents(eventGroupId);
|
|
205
|
+
}
|
|
206
|
+
async clearGroupedEvents(eventGroupId) {
|
|
207
|
+
if (!eventGroupId) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
await this.eventBusRedisConnection_.del(`staging:${eventGroupId}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
exports.default = RedisEventBusService;
|
|
214
|
+
//# sourceMappingURL=event-bus-redis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-bus-redis.js","sourceRoot":"","sources":["../../src/services/event-bus-redis.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["../src/index.ts","../src/initialize/index.ts","../src/loaders/index.ts","../src/services/event-bus-redis.ts","../src/services/__tests__/event-bus.ts","../src/types/index.ts"],"version":"5.6.2"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { BulkJobOptions, Job, JobsOptions, QueueOptions, WorkerOptions } from "bullmq";
|
|
2
|
+
import { RedisOptions } from "ioredis";
|
|
3
|
+
export type JobData<T> = {
|
|
4
|
+
eventName: string;
|
|
5
|
+
data: T;
|
|
6
|
+
completedSubscriberIds?: string[] | undefined;
|
|
7
|
+
};
|
|
8
|
+
export type Options = BulkJobOptions & {
|
|
9
|
+
groupedEventsTTL?: number;
|
|
10
|
+
internal?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export type BullJob<T> = {
|
|
13
|
+
data: JobData<T>;
|
|
14
|
+
opts: Job["opts"] & Options;
|
|
15
|
+
} & Job;
|
|
16
|
+
export type EmitOptions = JobsOptions;
|
|
17
|
+
export type EventBusRedisModuleOptions = {
|
|
18
|
+
queueName?: string;
|
|
19
|
+
queueOptions?: QueueOptions;
|
|
20
|
+
workerOptions?: WorkerOptions;
|
|
21
|
+
redisUrl?: string;
|
|
22
|
+
redisOptions?: RedisOptions;
|
|
23
|
+
/**
|
|
24
|
+
* Global options passed to all `EventBusService.emit` in the core as well as your own emitters. The options are forwarded to Bull's `Queue.add` method.
|
|
25
|
+
*
|
|
26
|
+
* The global options can be overridden by passing options to `EventBusService.emit` directly.
|
|
27
|
+
*
|
|
28
|
+
* Example
|
|
29
|
+
* ```js
|
|
30
|
+
* {
|
|
31
|
+
* removeOnComplete: { age: 10 },
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @see https://api.docs.bullmq.io/interfaces/BaseJobOptions.html
|
|
36
|
+
*/
|
|
37
|
+
jobOptions?: EmitOptions;
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,GAAG,EACH,WAAW,EACX,YAAY,EACZ,aAAa,EACd,MAAM,QAAQ,CAAA;AACf,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEtC,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,CAAC,CAAA;IACP,sBAAsB,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;CAC9C,CAAA;AAED,MAAM,MAAM,OAAO,GAAG,cAAc,GAAG;IACrC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI;IACvB,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IAChB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAAA;CAC5B,GAAG,GAAG,CAAA;AAEP,MAAM,MAAM,WAAW,GAAG,WAAW,CAAA;AAErC,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,YAAY,CAAA;IAE3B,aAAa,CAAC,EAAE,aAAa,CAAA;IAE7B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,YAAY,CAAA;IAE3B;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,WAAW,CAAA;CACzB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@etohq/event-bus-redis",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Redis Event Bus Module for Eto",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"!dist/**/__tests__",
|
|
9
|
+
"!dist/**/__mocks__",
|
|
10
|
+
"!dist/**/__fixtures__"
|
|
11
|
+
],
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/etohq/eto",
|
|
15
|
+
"directory": "packages/event-bus-redis"
|
|
16
|
+
},
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=20"
|
|
22
|
+
},
|
|
23
|
+
"author": "Eto",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@etohq/framework": "^1.0.0",
|
|
27
|
+
"@swc/core": "^1.7.28",
|
|
28
|
+
"@swc/jest": "^0.2.36",
|
|
29
|
+
"@types/jest": "^29.5.14",
|
|
30
|
+
"awilix": "^8.0.1",
|
|
31
|
+
"jest": "^29.7.0",
|
|
32
|
+
"rimraf": "^5.0.2",
|
|
33
|
+
"typescript": "^5.6.2"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"watch": "tsc --build --watch",
|
|
37
|
+
"build": "rimraf dist && tsc --build",
|
|
38
|
+
"test": "jest --silent --bail --maxWorkers=50% --forceExit"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"bullmq": "5.13.0",
|
|
42
|
+
"ioredis": "^5.4.1"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"@etohq/framework": "^1.0.0",
|
|
46
|
+
"awilix": "^8.0.1"
|
|
47
|
+
}
|
|
48
|
+
}
|