@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 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.
@@ -0,0 +1,6 @@
1
+ import { ModuleExports } from "@etohq/framework/types";
2
+ declare const moduleDefinition: ModuleExports;
3
+ export default moduleDefinition;
4
+ export * from "./initialize";
5
+ export * from "./types";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -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,4 @@
1
+ import { LoaderOptions } from "@etohq/framework/types";
2
+ declare const _default: ({ container, logger, options, }: LoaderOptions) => Promise<void>;
3
+ export default _default;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -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,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=index.js.map
@@ -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
+ }