woonplan-packages-redishelper 2.0.2 → 2.0.5

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.
@@ -0,0 +1,42 @@
1
+ /// <reference types="node" />
2
+ import { Redis } from "ioredis";
3
+ import Rollbar from "rollbar";
4
+ import Listener from "./Listener";
5
+ export default class Broker {
6
+ redisConfig: RedisConfig;
7
+ rollbar?: Rollbar;
8
+ consumername: string;
9
+ listeners: Map<string, Listener>;
10
+ writer: Redis;
11
+ reader: Redis;
12
+ listprefix: string;
13
+ service: string;
14
+ subscriptions: string[];
15
+ requestendpoint?: Function;
16
+ constructor(redisConfig: RedisConfig, rollbarConfig: RollbarConfig, service: string, consumer: string);
17
+ get requeststream(): string;
18
+ getRequestStream(service: string): string;
19
+ setRequestEndpoint(callback: Function): this;
20
+ getRequestCallback(callback: Function): (id: string, parameters: DecypheredParameters) => Promise<number | null>;
21
+ publish(channel: string, result: string): Promise<number>;
22
+ addListener(stream: string, callback: Function, group?: string): this;
23
+ addListListener(event: string, callback: Function): this;
24
+ throwError(error: Error): void;
25
+ sendMessage(stream: string, data: Struct): Promise<string | null>;
26
+ getRequest(targetservice: string, key: string, data: Struct): Promise<unknown>;
27
+ requestMessageResponse(resolve: (value?: any) => void, timeout: NodeJS.Timeout): void;
28
+ unsubscribe(channel: string): void;
29
+ setupTimeout(resolve: (value?: any) => void, channel: string, n?: number): NodeJS.Timeout;
30
+ subscribe(channel: string): Promise<unknown>;
31
+ getRequestSubscriptionName(messageid: string): string;
32
+ sendListEvent(event: string, listitems: any[], data?: Struct): Promise<string | null>;
33
+ addToList(listitems: any[], listname?: string): Promise<string>;
34
+ getListChannel(event: string): string;
35
+ sanitizeValue(value: any): any;
36
+ createRedisMessage(struct: Struct): string[];
37
+ getStreamMessages(stream: string): Promise<DecypheredMessage[]>;
38
+ getStreamInfo(stream: string, count?: number): Promise<any[] | null>;
39
+ filterStream(stream: string, key: string, value: any): Promise<DecypheredMessage[]>;
40
+ decypherResponse(...responses: StreamResponse[]): DecypheredResponse[];
41
+ decypherParameters(parameters: string[]): DecypheredParameters;
42
+ }
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const class_validator_1 = require("class-validator");
5
+ const ioredis_1 = tslib_1.__importDefault(require("ioredis"));
6
+ const rollbar_1 = tslib_1.__importDefault(require("rollbar"));
7
+ const types_1 = require("util/types");
8
+ const utils_1 = require("../services/utils");
9
+ const Listener_1 = tslib_1.__importDefault(require("./Listener"));
10
+ const ListListener_1 = tslib_1.__importDefault(require("./ListListener"));
11
+ const uuid_1 = require("uuid");
12
+ class Broker {
13
+ constructor(redisConfig, rollbarConfig, service, consumer) {
14
+ this.consumername = '';
15
+ this.listeners = new Map();
16
+ this.listprefix = 'listUpdated';
17
+ this.subscriptions = [];
18
+ this.redisConfig = redisConfig;
19
+ this.rollbar = new rollbar_1.default({
20
+ accessToken: rollbarConfig.accessToken,
21
+ environment: rollbarConfig.environment,
22
+ });
23
+ this.writer = new ioredis_1.default(redisConfig.REDISURL);
24
+ this.reader = new ioredis_1.default(redisConfig.REDISURL);
25
+ this.consumername = consumer;
26
+ this.service = service;
27
+ }
28
+ get requeststream() {
29
+ return this.getRequestStream(this.service);
30
+ }
31
+ getRequestStream(service) {
32
+ return `keyRequestedFrom${(0, utils_1.capitalizeFirstLetter)(service)}Service`;
33
+ }
34
+ setRequestEndpoint(callback) {
35
+ return this.addListener(this.requeststream, this.getRequestCallback(callback), this.service);
36
+ }
37
+ getRequestCallback(callback) {
38
+ return async (id, parameters) => {
39
+ const result = await callback(id, parameters);
40
+ if (!parameters.messageid)
41
+ return null;
42
+ const channel = this.getRequestSubscriptionName(parameters.messageid);
43
+ return this.publish(channel, result);
44
+ };
45
+ }
46
+ publish(channel, result) {
47
+ return this.writer.publish(channel, result);
48
+ }
49
+ addListener(stream, callback, group) {
50
+ const client = new ioredis_1.default(this.redisConfig.REDISURL);
51
+ this.listeners.set(stream, new Listener_1.default(this, client, stream, callback, group));
52
+ return this;
53
+ }
54
+ addListListener(event, callback) {
55
+ const client = new ioredis_1.default(this.redisConfig.REDISURL);
56
+ const channel = this.getListChannel(event);
57
+ this.listeners.set(channel, new ListListener_1.default(this, client, channel, callback));
58
+ return this;
59
+ }
60
+ throwError(error) {
61
+ if (!this.rollbar)
62
+ throw new Error('Rollbar not initialized');
63
+ this.rollbar.error(error);
64
+ }
65
+ sendMessage(stream, data) {
66
+ return this.writer.xadd(stream, '*', ...this.createRedisMessage(data));
67
+ }
68
+ async getRequest(targetservice, key, data) {
69
+ // create a message id to subscribe to
70
+ const messageid = (0, uuid_1.v4)();
71
+ //subscribe to message response
72
+ const channel = this.getRequestSubscriptionName(messageid);
73
+ await this.subscribe(channel);
74
+ // send the message to the correct service
75
+ this.sendMessage(this.getRequestStream(targetservice), {
76
+ request: key,
77
+ messageid: messageid,
78
+ data: data
79
+ });
80
+ let resolver;
81
+ // create a promise to be able to pass on to resolve later
82
+ const promise = new Promise((r) => {
83
+ resolver = r;
84
+ });
85
+ if (!resolver)
86
+ return null;
87
+ //setup a timeout
88
+ const timeout = this.setupTimeout(resolver, channel);
89
+ //setup a response
90
+ this.requestMessageResponse(resolver, timeout);
91
+ // return a promise that will resolve when the message returns or times out
92
+ return promise;
93
+ }
94
+ requestMessageResponse(resolve, timeout) {
95
+ this.reader.once('message', (channel, message) => {
96
+ if (message.length)
97
+ resolve(message);
98
+ else
99
+ resolve(null);
100
+ this.unsubscribe(channel);
101
+ clearTimeout(timeout);
102
+ });
103
+ }
104
+ unsubscribe(channel) {
105
+ this.reader.unsubscribe(channel);
106
+ this.subscriptions = this.subscriptions.filter(s => s != channel);
107
+ }
108
+ setupTimeout(resolve, channel, n = 2000) {
109
+ return setTimeout(() => {
110
+ if (!this.subscriptions.includes(channel))
111
+ return;
112
+ console.log(`sub timedout: ${channel}`);
113
+ resolve(null);
114
+ this.unsubscribe(channel);
115
+ }, n);
116
+ }
117
+ subscribe(channel) {
118
+ this.subscriptions.push(channel);
119
+ return this.reader.subscribe(channel);
120
+ }
121
+ getRequestSubscriptionName(messageid) {
122
+ return `messageresponse${messageid}`;
123
+ }
124
+ async sendListEvent(event, listitems, data = {}) {
125
+ const list = await this.addToList.call(this, listitems);
126
+ return this.sendMessage(this.getListChannel(event), {
127
+ ...data,
128
+ listname: list
129
+ });
130
+ }
131
+ async addToList(listitems, listname) {
132
+ const list = listname ?? (0, uuid_1.v4)();
133
+ await this.writer.lpush(list, ...listitems.map(this.sanitizeValue));
134
+ return list;
135
+ }
136
+ getListChannel(event) {
137
+ return `${this.listprefix}${event}`;
138
+ }
139
+ sanitizeValue(value) {
140
+ if ((0, types_1.isMap)(value))
141
+ return (0, utils_1.stringifyMap)(value);
142
+ if ((0, class_validator_1.isObject)(value))
143
+ return JSON.stringify(value);
144
+ if ((0, class_validator_1.isArray)(value))
145
+ return JSON.stringify(value);
146
+ return value;
147
+ }
148
+ createRedisMessage(struct) {
149
+ return Object.keys(struct).reduce((arr, key) => [...arr, key, this.sanitizeValue(struct[key])], []);
150
+ }
151
+ async getStreamMessages(stream) {
152
+ const streaminfo = await this.getStreamInfo.call(this, stream);
153
+ if (!streaminfo || !(0, class_validator_1.isArray)(streaminfo) || streaminfo.length < 10)
154
+ return [];
155
+ const streamresponses = streaminfo[9];
156
+ return this.decypherResponse(...streamresponses).flatMap(r => r.messages);
157
+ }
158
+ getStreamInfo(stream, count = 0) {
159
+ return this.reader.xinfo('STREAM', stream, 'FULL', 'COUNT', count);
160
+ }
161
+ async filterStream(stream, key, value) {
162
+ const messages = await this.getStreamMessages.call(this, stream);
163
+ return messages.filter(message => message.parameters?.[key] != null && message.parameters[key] == value);
164
+ }
165
+ decypherResponse(...responses) {
166
+ return responses.reduce((resp, response) => [
167
+ ...resp,
168
+ {
169
+ stream: response[0],
170
+ messages: response[1].map((message) => ({
171
+ id: message[0],
172
+ parameters: this.decypherParameters(message[1])
173
+ }))
174
+ }
175
+ ], []);
176
+ }
177
+ decypherParameters(parameters) {
178
+ return parameters.reduce((params, v, n) => (n == 0 || (n % 2 == 0)) && parameters.length >= n + 1 ? ({
179
+ ...params,
180
+ [v]: parameters[n + 1]
181
+ }) : params, {});
182
+ }
183
+ }
184
+ exports.default = Broker;
185
+ //# sourceMappingURL=Broker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Broker.js","sourceRoot":"","sources":["../../../src/classes/Broker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { Redis } from "ioredis";
2
+ import Broker from "./Broker";
3
+ export default abstract class BrokerClient {
4
+ broker: Broker;
5
+ client: Redis;
6
+ group: string | null;
7
+ stream: string | null;
8
+ list: string | null;
9
+ callback: Function;
10
+ constructor(broker: Broker, client: Redis, callback: Function, list: string | null, stream?: string | null, group?: string | null);
11
+ throwError(error: any): void;
12
+ decypherResponse(...responses: StreamResponse[]): DecypheredResponse[];
13
+ getGroupResponse(): Promise<StreamResponse[] | null>;
14
+ getResponse(lastid: string): Promise<StreamResponse[] | null>;
15
+ listenToStream(lastid?: string): Promise<Function | null>;
16
+ abstract streamCallback(message: DecypheredMessage): Promise<any | null>;
17
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class BrokerClient {
4
+ constructor(broker, client, callback, list, stream = null, group = null) {
5
+ this.group = null;
6
+ this.stream = null;
7
+ this.list = null;
8
+ this.broker = broker;
9
+ this.client = client;
10
+ this.list = list;
11
+ this.stream = stream;
12
+ this.group = group;
13
+ this.callback = callback;
14
+ this.listenToStream.call(this);
15
+ }
16
+ throwError(error) {
17
+ return this.broker.throwError(error);
18
+ }
19
+ decypherResponse(...responses) {
20
+ return this.broker.decypherResponse(...responses);
21
+ }
22
+ async getGroupResponse() {
23
+ if (!this.group || !this.stream)
24
+ return null;
25
+ return await this.client.xreadgroup('GROUP', this.group, this.broker.consumername, 'COUNT', 1, 'BLOCK', 0, 'STREAMS', this.stream, '>');
26
+ }
27
+ async getResponse(lastid) {
28
+ if (!this.stream)
29
+ return null;
30
+ return await this.client.xread("BLOCK", 0, "STREAMS", this.stream, lastid);
31
+ }
32
+ async listenToStream(lastid = '$') {
33
+ const responses = await this.getResponse.call(this, lastid);
34
+ if (!responses)
35
+ return null;
36
+ const streamResponses = this.decypherResponse(...responses);
37
+ const messages = streamResponses.flatMap(r => r.messages);
38
+ await Promise.all(messages.map(async (message) => {
39
+ try {
40
+ await this.streamCallback(message);
41
+ }
42
+ catch (e) {
43
+ this.broker.throwError(e);
44
+ }
45
+ finally {
46
+ }
47
+ }));
48
+ return this.listenToStream.call(this, messages[messages.length - 1]?.id ?? '$');
49
+ }
50
+ }
51
+ exports.default = BrokerClient;
52
+ //# sourceMappingURL=BrokerClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BrokerClient.js","sourceRoot":"","sources":["../../../src/classes/BrokerClient.ts"],"names":[],"mappings":";;AAGA,MAA8B,YAAY;IAQxC,YAAa,MAAa,EAAE,MAAY,EAAE,QAAiB,EAAE,IAAkB,EAAE,SAAuB,IAAI,EAAE,QAAuB,IAAI;QALzI,UAAK,GAAmB,IAAI,CAAA;QAC5B,WAAM,GAAmB,IAAI,CAAA;QAC7B,SAAI,GAAmB,IAAI,CAAA;QAIzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QAExB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAE,IAAI,CAAE,CAAA;IAClC,CAAC;IAED,UAAU,CAAE,KAAS;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAE,KAAK,CAAE,CAAA;IACxC,CAAC;IAED,gBAAgB,CAAE,GAAG,SAA0B;QAC7C,OAAO,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAE,GAAG,SAAS,CAAE,CAAA;IACrD,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM;YAAG,OAAO,IAAI,CAAA;QAC7C,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAE,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,CAAuB,CAAA;IAChK,CAAC;IAED,KAAK,CAAC,WAAW,CAAE,MAAa;QAC9B,IAAI,CAAC,IAAI,CAAC,MAAM;YAAG,OAAO,IAAI,CAAA;QAC9B,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAE,CAAA;IAC7E,CAAC;IAGD,KAAK,CAAC,cAAc,CAAE,SAAgB,GAAG;QACvC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAE,IAAI,EAAE,MAAM,CAAE,CAAA;QAC7D,IAAI,CAAC,SAAS;YAAG,OAAO,IAAI,CAAA;QAE5B,MAAM,eAAe,GAAG,IAAI,CAAC,gBAAgB,CAAE,GAAG,SAAS,CAAE,CAAA;QAC7D,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAE,CAAA;QAC3D,MAAM,OAAO,CAAC,GAAG,CAAE,QAAQ,CAAC,GAAG,CAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACjD,IAAG;gBACD,MAAM,IAAI,CAAC,cAAc,CAAE,OAAO,CAAE,CAAA;aAErC;YAAA,OAAO,CAAK,EAAE;gBACb,IAAI,CAAC,MAAM,CAAC,UAAU,CAAE,CAAC,CAAE,CAAA;aAC5B;oBAAO;aAEP;QACH,CAAC,CAAC,CAAE,CAAA;QAEJ,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAC,CAAC,CAAC,EAAE,EAAE,IAAE,GAAG,CAAE,CAAA;IAC/E,CAAC;CAGF;AA3DD,+BA2DC"}
@@ -0,0 +1,8 @@
1
+ import { Redis } from "ioredis";
2
+ import Broker from "./Broker";
3
+ import BrokerClient from "./BrokerClient";
4
+ import ListRunner from "./ListRunner";
5
+ export default class Listener extends BrokerClient {
6
+ constructor(broker: Broker, client: Redis, list: string, callback: Function);
7
+ streamCallback(message: DecypheredMessage): Promise<ListRunner | null>;
8
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const BrokerClient_1 = tslib_1.__importDefault(require("./BrokerClient"));
5
+ const ListRunner_1 = tslib_1.__importDefault(require("./ListRunner"));
6
+ class Listener extends BrokerClient_1.default {
7
+ constructor(broker, client, list, callback) {
8
+ super(broker, client, callback, list);
9
+ }
10
+ async streamCallback(message) {
11
+ const listrunnercallback = await this.callback(message.id, message.parameters);
12
+ if (message.parameters.listname)
13
+ return new ListRunner_1.default(this.client, message.parameters.listname, listrunnercallback);
14
+ return null;
15
+ }
16
+ }
17
+ exports.default = Listener;
18
+ //# sourceMappingURL=ListListener.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ListListener.js","sourceRoot":"","sources":["../../../src/classes/ListListener.ts"],"names":[],"mappings":";;;AAEA,0EAAyC;AACzC,sEAAqC;AAErC,MAAqB,QAAS,SAAQ,sBAAY;IAChD,YAAa,MAAa,EAAE,MAAY,EAAE,IAAW,EAAE,QAAiB;QACtE,KAAK,CAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAE,CAAA;IACzC,CAAC;IAED,KAAK,CAAC,cAAc,CAAE,OAAyB;QAC7C,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAE,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,UAAU,CAAE,CAAA;QAEhF,IAAI,OAAO,CAAC,UAAU,CAAC,QAAQ;YAC7B,OAAO,IAAI,oBAAU,CAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAA;QAEtF,OAAO,IAAI,CAAA;IACb,CAAC;CACF;AAbD,2BAaC"}
@@ -0,0 +1,11 @@
1
+ import { Redis } from "ioredis";
2
+ export default class ListRunner {
3
+ listname: string;
4
+ itemsDone: number;
5
+ itemsPerCall: number;
6
+ callback: Function;
7
+ client: Redis;
8
+ constructor(client: Redis, listname: string, callback: Function, itemsPerCall?: number);
9
+ run(): Promise<Function | void>;
10
+ nextitems(listname: string): Promise<string[] | null>;
11
+ }
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class ListRunner {
4
+ constructor(client, listname, callback, itemsPerCall = 1) {
5
+ this.itemsDone = 0;
6
+ this.client = client;
7
+ this.callback = callback;
8
+ this.listname = listname;
9
+ this.itemsPerCall = itemsPerCall;
10
+ this.run.call(this);
11
+ }
12
+ async run() {
13
+ const items = await this.nextitems.call(this, this.listname);
14
+ if (!items) {
15
+ console.log(`finished with ${this.itemsDone} jobs`);
16
+ return;
17
+ }
18
+ try {
19
+ await this.callback(items);
20
+ }
21
+ catch (e) {
22
+ console.log(e);
23
+ }
24
+ finally {
25
+ this.itemsDone += this.itemsPerCall;
26
+ return this.run.call(this);
27
+ }
28
+ }
29
+ async nextitems(listname) {
30
+ return this.client.lpop(listname, this.itemsPerCall);
31
+ }
32
+ }
33
+ exports.default = ListRunner;
34
+ //# sourceMappingURL=ListRunner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ListRunner.js","sourceRoot":"","sources":["../../../src/classes/ListRunner.ts"],"names":[],"mappings":";;AAEA,MAAqB,UAAU;IAQ7B,YAAa,MAAY,EAAE,QAAe,EAAE,QAAiB,EAAE,eAAwB,CAAC;QANxF,cAAS,GAAU,CAAC,CAAA;QAOlB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA;QAEhC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAE,IAAI,CAAE,CAAA;IACvB,CAAC;IAGD,KAAK,CAAC,GAAG;QACP,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAE,CAAA;QAC9D,IAAI,CAAC,KAAK,EAAE;YACV,OAAO,CAAC,GAAG,CAAE,iBAAiB,IAAI,CAAC,SAAS,OAAO,CAAC,CAAA;YACpD,OAAM;SACP;QAED,IAAG;YACD,MAAM,IAAI,CAAC,QAAQ,CAAE,KAAK,CAAE,CAAA;SAC7B;QAAA,OAAO,CAAK,EAAE;YACb,OAAO,CAAC,GAAG,CAAE,CAAC,CAAE,CAAA;SAEjB;gBAAO;YACN,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,YAAY,CAAA;YACnC,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAE,IAAI,CAAE,CAAA;SAC7B;IACH,CAAC;IAED,KAAK,CAAC,SAAS,CAAE,QAAe;QAC9B,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAE,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAE,CAAA;IACxD,CAAC;CAEF;AAxCD,6BAwCC"}
@@ -0,0 +1,7 @@
1
+ import { Redis } from "ioredis";
2
+ import Broker from "./Broker";
3
+ import BrokerClient from "./BrokerClient";
4
+ export default class Listener extends BrokerClient {
5
+ constructor(broker: Broker, client: Redis, stream: string, callback: Function, group?: string);
6
+ streamCallback(message: DecypheredMessage): Promise<any>;
7
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const BrokerClient_1 = tslib_1.__importDefault(require("./BrokerClient"));
5
+ class Listener extends BrokerClient_1.default {
6
+ constructor(broker, client, stream, callback, group) {
7
+ super(broker, client, callback, null, stream, group);
8
+ }
9
+ streamCallback(message) {
10
+ return this.callback(message.id, message.parameters);
11
+ }
12
+ }
13
+ exports.default = Listener;
14
+ //# sourceMappingURL=Listener.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Listener.js","sourceRoot":"","sources":["../../../src/classes/Listener.ts"],"names":[],"mappings":";;;AAEA,0EAAyC;AAEzC,MAAqB,QAAS,SAAQ,sBAAY;IAChD,YAAa,MAAa,EAAE,MAAY,EAAE,MAAa,EAAE,QAAiB,EAAE,KAAe;QACzF,KAAK,CAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAE,CAAA;IACxD,CAAC;IAED,cAAc,CAAC,OAA0B;QACvC,OAAO,IAAI,CAAC,QAAQ,CAAE,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,UAAU,CAAE,CAAA;IACxD,CAAC;CACF;AARD,2BAQC"}
@@ -0,0 +1,2 @@
1
+ import Broker from "./classes/Broker";
2
+ export { Broker };
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Broker = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const Broker_1 = tslib_1.__importDefault(require("./classes/Broker"));
6
+ exports.Broker = Broker_1.default;
7
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/main.ts"],"names":[],"mappings":";;;;AAAA,sEAAqC;AAE5B,iBAFF,gBAAM,CAEE"}
@@ -0,0 +1,11 @@
1
+ declare const isJSON: (str: any) => boolean;
2
+ interface ObjectToOmitFrom {
3
+ [index: string]: any;
4
+ }
5
+ declare const omit: (objectToOmitFrom: ObjectToOmitFrom, keys: (keyof ObjectToOmitFrom)[]) => {};
6
+ declare const mapJsonReplacer: (_key: any, value: Map<any, any> | any) => any;
7
+ declare const mapJsonReviver: (_key: any, value: JsonStringifiedMap | any) => any;
8
+ declare const stringifyMap: (map: Map<any, any>) => string;
9
+ declare const parseMap: (json: string) => Map<any, any>;
10
+ declare const capitalizeFirstLetter: (string: string) => string;
11
+ export { isJSON, omit, mapJsonReviver, stringifyMap, parseMap, mapJsonReplacer, capitalizeFirstLetter };
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.capitalizeFirstLetter = exports.mapJsonReplacer = exports.parseMap = exports.stringifyMap = exports.mapJsonReviver = exports.omit = exports.isJSON = void 0;
4
+ const isJSON = (str) => {
5
+ if (typeof str == 'number')
6
+ return false;
7
+ try {
8
+ JSON.parse(str);
9
+ }
10
+ catch (error) {
11
+ return false;
12
+ }
13
+ return true;
14
+ };
15
+ exports.isJSON = isJSON;
16
+ const omit = (objectToOmitFrom, keys) => Object.keys(objectToOmitFrom)
17
+ .filter(key => keys.indexOf(key) == -1)
18
+ .reduce((struct, key) => Object.assign(struct, { [key]: objectToOmitFrom[key] }), {});
19
+ exports.omit = omit;
20
+ const mapJsonReplacer = (_key, value) => {
21
+ if (value instanceof Map) {
22
+ return {
23
+ dataType: 'Map',
24
+ value: Array.from(value.entries()), // or with spread: value: [...value]
25
+ };
26
+ }
27
+ else {
28
+ return value;
29
+ }
30
+ };
31
+ exports.mapJsonReplacer = mapJsonReplacer;
32
+ const mapJsonReviver = (_key, value) => {
33
+ if (typeof value === 'object' && value !== null) {
34
+ if (value.dataType === 'Map') {
35
+ return new Map(value.value);
36
+ }
37
+ }
38
+ return value;
39
+ };
40
+ exports.mapJsonReviver = mapJsonReviver;
41
+ const stringifyMap = (map) => JSON.stringify(map, exports.mapJsonReplacer);
42
+ exports.stringifyMap = stringifyMap;
43
+ const parseMap = (json) => JSON.parse(json, exports.mapJsonReviver);
44
+ exports.parseMap = parseMap;
45
+ const capitalizeFirstLetter = (string) => string.charAt(0).toUpperCase() + string.slice(1);
46
+ exports.capitalizeFirstLetter = capitalizeFirstLetter;
47
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/services/utils.ts"],"names":[],"mappings":";;;AAAA,MAAM,MAAM,GAAG,CAAE,GAAO,EAAG,EAAE;IAC3B,IAAI,OAAO,GAAG,IAAI,QAAQ;QAAG,OAAO,KAAK,CAAA;IACzC,IAAG;QACD,IAAI,CAAC,KAAK,CAAE,GAAG,CAAE,CAAA;KAClB;IAAA,OAAO,KAAK,EAAE;QACb,OAAO,KAAK,CAAC;KACd;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAA;AAyCQ,wBAAM;AAlCf,MAAM,IAAI,GAAG,CAAE,gBAAiC,EAAE,IAA+B,EAAE,EAAE,CACrF,MAAM,CAAC,IAAI,CAAE,gBAAgB,CAAE;KAC9B,MAAM,CAAE,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAE,GAAG,CAAE,IAAI,CAAC,CAAC,CAAE;KAC1C,MAAM,CAAE,CAAC,MAAa,EAAC,GAAG,EAAE,EAAE,CAC7B,MAAM,CAAC,MAAM,CAAE,MAAM,EAAE,EAAC,CAAC,GAAG,CAAC,EAAC,gBAAgB,CAAC,GAAG,CAAC,EAAC,CAAE,EACtD,EAAE,CACH,CAAA;AA4BgB,oBAAI;AAxBrB,MAAM,eAAe,GAAG,CAAE,IAAQ,EAAE,KAAwB,EAAG,EAAE;IAC/D,IAAG,KAAK,YAAY,GAAG,EAAE;QACvB,OAAO;YACL,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,oCAAoC;SACnD,CAAA;KACxB;SAAM;QACL,OAAO,KAAK,CAAC;KACd;AACH,CAAC,CAAA;AAe8D,0CAAe;AAb9E,MAAM,cAAc,GAAG,CAAE,IAAQ,EAAE,KAA8B,EAAG,EAAE;IACpE,IAAG,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE;QAC9C,IAAI,KAAK,CAAC,QAAQ,KAAK,KAAK,EAAE;YAC5B,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;SAC7B;KACF;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAA;AAMsB,wCAAc;AAJrC,MAAM,YAAY,GAAG,CAAE,GAAgB,EAAS,EAAE,CAAC,IAAI,CAAC,SAAS,CAAE,GAAG,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;AAIzD,oCAAY;AAHnD,MAAM,QAAQ,GAAG,CAAE,IAAW,EAAgB,EAAE,CAAC,IAAI,CAAC,KAAK,CAAE,IAAI,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;AAGrC,4BAAQ;AAF7D,MAAM,qBAAqB,GAAG,CAAC,MAAa,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AAEjB,sDAAqB"}
@@ -46,4 +46,4 @@ interface DecypheredResponse{
46
46
  interface RollbarConfig{
47
47
  accessToken : string
48
48
  environment : string
49
- }
49
+ }
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "woonplan-packages-redishelper",
3
- "version": "2.0.2",
3
+ "version": "2.0.5",
4
4
  "description": "",
5
5
  "author": "Jasper Denk <jasper@e-trias.nl>",
6
6
  "repository": "https://github.com/e-line-websolutions/woonplan-micro-energyio",
7
7
  "license": "MIT",
8
8
  "keywords": [],
9
9
  "main": "./dist/tsc/main.js",
10
- "types": "./dist/tsc/main.d.ts",
10
+ "types": "./dist/tsc/types.d.ts",
11
11
  "scripts": {
12
12
  "dev": "ts-node --esm src/main.ts",
13
13
  "lint": "eslint src/ --ext .js,.jsx,.ts,.tsx",
package/tsconfig.json CHANGED
@@ -26,7 +26,7 @@
26
26
  "lib": [
27
27
  "ES6",
28
28
  "DOM"
29
- ]
29
+ ],
30
30
  },
31
31
  "include": [
32
32
  "src/**/*.ts"
package/jest.config.js DELETED
@@ -1,18 +0,0 @@
1
- module.exports = {
2
- roots: ['<rootDir>/src'
3
- ],
4
- testMatch: [
5
- "**/__tests__/**/*.+(ts|tsx|js)",
6
- "**/?(*.)+(spec|test).+(ts|tsx|js)"
7
- ],
8
- transform: {
9
- "^.+\\.(ts|tsx)$": "ts-jest"
10
- },
11
- testTimeout: 500,
12
- globals: {
13
- 'ts-jest': {
14
- isolatedModules: true
15
- }
16
- },
17
- preset: 'ts-jest/presets/js-with-ts'
18
- }
@@ -1,223 +0,0 @@
1
-
2
-
3
- import Broker from '../classes/Broker'
4
- import Listener from '../classes/Listener'
5
- import { DecypheredMessage, RedisConfig, RollbarConfig } from '../types'
6
- import { stringifyMap } from "../services/utils"
7
- import Redis from "ioredis-mock"
8
-
9
- jest.mock( 'ioredis', () => require("ioredis-mock") )
10
- // jest.mock( '../classes/Listener' )
11
-
12
- const cb = () => {}
13
-
14
-
15
- const rollbarConfig:RollbarConfig = {
16
- environment : '',
17
- accessToken : ''
18
- }
19
- const redisConfig:RedisConfig = {
20
- REDISURL : ''
21
- }
22
-
23
- const service = "testservice",
24
- consumer = "testconsumer"
25
-
26
- xdescribe("addListener", () => {
27
- afterEach(()=>jest.clearAllMocks())
28
- it("should create a Listener class", () => {
29
- new Broker(
30
- redisConfig,
31
- rollbarConfig,
32
- service,
33
- consumer
34
- ).addListener( '', cb )
35
-
36
- expect( Listener ).toHaveBeenCalled( )
37
- })
38
- it("should be chainable", () => {
39
- new Broker(
40
- redisConfig,
41
- rollbarConfig,
42
- service,
43
- consumer
44
- ).addListener( '', cb ).addListener( '', cb ).addListener( '', cb )
45
-
46
- expect( Listener ).toHaveBeenCalledTimes( 3 )
47
- })
48
- })
49
-
50
- describe("sanitize",()=>{
51
- const broker = new Broker( redisConfig, rollbarConfig,
52
- service,
53
- consumer )
54
- it("should return a json map if a map is given" ,() => {
55
- expect( broker.sanitizeValue( new Map() ) ).toStrictEqual( stringifyMap(new Map()))
56
- })
57
- it("should return a number if a number is given" ,() => {
58
- expect( broker.sanitizeValue( 1 )).toStrictEqual( 1 )
59
- })
60
- it("should return a string if a string is given" ,() => {
61
- expect( broker.sanitizeValue( 'foo' ) ).toStrictEqual( 'foo' )
62
- })
63
- it("should return a JSON array if an array is given" ,() => {
64
- expect( broker.sanitizeValue( ['foo'] ) ).toStrictEqual( JSON.stringify( ['foo']))
65
- })
66
- it("should return a JSON object if an object is given" ,() => {
67
- expect( broker.sanitizeValue( {'foo':'bar'} ) ).toStrictEqual( JSON.stringify( {'foo':'bar'} ))
68
- })
69
- })
70
-
71
- describe("createRedisMessage", () => {
72
- const broker = new Broker( redisConfig, rollbarConfig,
73
- service,
74
- consumer )
75
- it("should create a redis message array from an object ", () => {
76
- expect( broker.createRedisMessage({
77
- foo : 'bar',
78
- bar : ['baz'],
79
- hello : new Map( [['world','foo']])
80
- })).toStrictEqual(
81
- ['foo','bar','bar',JSON.stringify( ['baz']),'hello', stringifyMap(new Map( [['world','foo']]))]
82
- )
83
- })
84
- })
85
-
86
- jest.setTimeout( 2500 )
87
-
88
- describe("getRequest", () => {
89
- it("should add a subscription" , async () => {
90
- const broker = new Broker( redisConfig, rollbarConfig,
91
- service,
92
- consumer )
93
-
94
- broker.getRequest( 'foo', 'bar', {})
95
- const mockresult = new Redis()
96
- mockresult.publish( broker.subscriptions[0], 'baz')
97
- expect( broker.subscriptions.length > 0 ).toBe( true )
98
- await broker
99
- })
100
- it("should return a response" , async () => {
101
- const broker = new Broker( redisConfig, rollbarConfig,
102
- service,
103
- consumer )
104
-
105
- const result = broker.getRequest( 'foo', 'bar', {})
106
-
107
- const mockresult = new Redis()
108
- mockresult.publish( broker.subscriptions[0], 'baz')
109
- expect( await result ).toStrictEqual( 'baz' )
110
- })
111
- it("should return a timeout and null if no response is given within timeout" , async () => {
112
- const broker = new Broker( redisConfig, rollbarConfig,
113
- service,
114
- consumer )
115
-
116
- const result = broker.getRequest( 'foo', 'bar', {})
117
- expect( await result ).toStrictEqual( null )
118
-
119
- })
120
- })
121
-
122
- // Unable to test this untill ioredis-mock has a xreadgroup
123
- xdescribe("requester",()=>{
124
- it("should send a request and be able to receive", async () => {
125
- const receiver = new Broker( redisConfig, rollbarConfig, 'foo', consumer )
126
-
127
- const requestEndpoint = jest.fn(() => {
128
- console.log( 'requestendpoint hit')
129
- return 'baz'
130
- })
131
- receiver.setRequestEndpoint( requestEndpoint )
132
-
133
- const requester = new Broker( redisConfig, rollbarConfig, 'bar', consumer )
134
-
135
- const request = await requester.getRequest( 'foo', 'key', {} )
136
-
137
- expect( request ).toStrictEqual( 'baz' )
138
-
139
-
140
- })
141
- })
142
-
143
- xdescribe( "getRequest", () => {
144
- afterEach(() => jest.clearAllMocks())
145
- it("should subscribe to a channel", async ()=>{
146
- const spy = jest.spyOn( Broker.prototype, 'subscribe' ).mockResolvedValueOnce( null )
147
- const broker = new Broker( redisConfig, rollbarConfig, 'foo', consumer )
148
-
149
-
150
- jest.spyOn( Broker.prototype, 'requestMessageResponse' ).mockImplementation((resolve, timeout) => {
151
- resolve()
152
- clearTimeout( timeout )
153
- })
154
- broker.getRequest( 'foo', 'bar', {} )
155
-
156
- expect( spy ).toBeCalled( )
157
- })
158
- it("should setup a message response", async ()=>{
159
- jest.spyOn( Broker.prototype, 'subscribe' ).mockResolvedValueOnce( null )
160
-
161
-
162
- const spy = jest.spyOn( Broker.prototype, 'requestMessageResponse' ).mockImplementation((resolve, timeout) => {
163
- console.log( 1 )
164
- resolve()
165
- clearTimeout( timeout )
166
- })
167
-
168
- const broker = new Broker( redisConfig, rollbarConfig, 'foo', consumer )
169
- broker.getRequest( 'foo', 'bar', {} )
170
- expect( spy ).toBeCalled( )
171
- })
172
- it("should setup a timeout", async ()=>{
173
- jest.spyOn( Broker.prototype, 'subscribe' ).mockResolvedValueOnce( null )
174
-
175
- jest.spyOn( Broker.prototype, 'requestMessageResponse' ).mockImplementation((resolve, timeout) => {
176
- resolve()
177
- clearTimeout( timeout )
178
- })
179
-
180
- const spy = jest.spyOn( Broker.prototype, 'setupTimeout' ).mockImplementation((_resolve, channel) => {
181
- return setTimeout(() => {
182
-
183
- }, 200);
184
- })
185
-
186
- const broker = new Broker( redisConfig, rollbarConfig, 'foo', consumer )
187
- broker.getRequest( 'foo', 'bar', {} )
188
- expect( spy ).toBeCalled( )
189
- })
190
- })
191
-
192
-
193
-
194
- const responses = [['foo',[['bar',['id','baz']],['bar',['id','baz1']],['bar',['id','baz2']]]]]
195
-
196
- describe("filterStream", () => {
197
- it("should filter the stream and only give back the messages with the request parameters", async () => {
198
- jest.spyOn( Broker.prototype, 'getStreamInfo' ).mockResolvedValue( [0,1,2,3,4,5,6,7,8,responses] )
199
- const broker = new Broker( redisConfig, rollbarConfig, 'foo', consumer )
200
-
201
- expect( await broker.filterStream( 'foo', 'id', 'baz') ).toStrictEqual([{
202
- id : 'bar',
203
- parameters : {
204
- id : 'baz'
205
- }
206
-
207
- }])
208
-
209
- })
210
- })
211
-
212
- describe("addListListener", () => {
213
-
214
- const broker = new Broker( redisConfig, rollbarConfig, 'foo', consumer )
215
-
216
- const listcb = ( id:string ) => {
217
- console.log( id )
218
- }
219
- const messagecb = ( message:DecypheredMessage ) => listcb( message.id )
220
-
221
-
222
- broker.addListListener('measuredataschanged', messagecb )
223
- })
@@ -1,89 +0,0 @@
1
- import Broker from "../classes/Broker"
2
- import Listener from "../classes/Listener"
3
- import { RedisConfig, RollbarConfig } from "../types"
4
-
5
- const cb = jest.fn()
6
-
7
-
8
- const rollbarConfig:RollbarConfig = {
9
- environment : '',
10
- accessToken : ''
11
- }
12
-
13
- const redisConfig:RedisConfig = {
14
- REDISURL : ''
15
- }
16
-
17
- const responses = [['foo',[['bar',['id','baz']]]]]
18
-
19
- jest.mock( 'ioredis', () => jest.fn().mockImplementation(() => {
20
- return {
21
- xread: jest.fn(( _a,_b,_c,_d,e) => {
22
- if( e == 'bar' ) return null
23
- return responses
24
- }),
25
-
26
- xreadgroup: jest.fn(() => {
27
- return null
28
- })
29
-
30
- }
31
- }) )
32
-
33
- describe("listenToStream", () => {
34
- afterEach(() => jest.clearAllMocks())
35
- it("should call xreadgroup if a groupname is given", async () => {
36
- const broker = new Broker(
37
- redisConfig,
38
- rollbarConfig
39
- ).addListener( 'stream', cb, 'groupname' )
40
-
41
- await new Promise((r) => setTimeout(r, 100))
42
- expect( broker.listeners.get( 'stream')?.client.xreadgroup ).toHaveBeenCalled()
43
- expect( broker.listeners.get( 'stream')?.client.xread ).not.toHaveBeenCalled()
44
- })
45
- it("should call xread if a groupname is not given", async () => {
46
- const broker = new Broker(
47
- redisConfig,
48
- rollbarConfig
49
- ).addListener( 'stream', cb )
50
-
51
- await new Promise((r) => setTimeout(r, 100))
52
-
53
- expect( broker.listeners.get( 'stream')?.client.xreadgroup ).not.toHaveBeenCalled()
54
- expect( broker.listeners.get( 'stream')?.client.xread ).toHaveBeenCalled()
55
- })
56
-
57
- it("should call the callback if a message comes in from the stream ", async ()=>{
58
-
59
- new Broker(
60
- redisConfig,
61
- rollbarConfig
62
- ).addListener( '', cb )
63
-
64
- await new Promise((r) => setTimeout(r, 100))
65
-
66
- expect( cb ).toHaveBeenCalledWith( 'bar', {
67
- id : 'baz'
68
- })
69
-
70
- })
71
-
72
-
73
- it("should report an error", async () => {
74
-
75
- const errormock = jest.fn( () => {
76
- throw new Error('foo')
77
- })
78
-
79
- const spy = jest.spyOn( Broker.prototype, 'throwError')
80
- new Broker(
81
- redisConfig,
82
- rollbarConfig
83
- ).addListener( 'stream', errormock )
84
-
85
- await new Promise((r) => setTimeout(r, 100))
86
-
87
- expect( spy ).toHaveBeenCalled( )
88
- })
89
- })
@@ -1,224 +0,0 @@
1
- import { isArray, isObject } from "class-validator"
2
- import IORedis, { Redis } from "ioredis"
3
- import Rollbar from "rollbar"
4
- import { isMap } from "util/types"
5
- import { capitalizeFirstLetter, stringifyMap } from "../services/utils"
6
- import Listener from "./Listener"
7
- import ListListener from "./ListListener"
8
- import { v4 as uuidv4 } from 'uuid'
9
-
10
- export default class Broker{
11
- redisConfig : RedisConfig
12
- rollbar ?: Rollbar
13
- consumername : string = ''
14
- listeners: Map<string,Listener> = new Map()
15
- writer : Redis
16
- reader : Redis
17
- listprefix : string = 'listUpdated'
18
- service: string
19
- subscriptions : string[] = []
20
-
21
- requestendpoint ?: Function
22
-
23
- constructor( redisConfig:RedisConfig, rollbarConfig:RollbarConfig, service:string, consumer : string ){
24
- this.redisConfig = redisConfig
25
- this.rollbar = new Rollbar({
26
- accessToken: rollbarConfig.accessToken,
27
- environment: rollbarConfig.environment,
28
- })
29
- this.writer = new IORedis( redisConfig.REDISURL as string )
30
- this.reader = new IORedis( redisConfig.REDISURL as string )
31
- this.consumername = consumer
32
- this.service = service
33
- }
34
-
35
- get requeststream(){
36
- return this.getRequestStream( this.service )
37
- }
38
-
39
- getRequestStream( service:string ){
40
- return `keyRequestedFrom${capitalizeFirstLetter(service)}Service`
41
- }
42
-
43
- setRequestEndpoint( callback:Function ){
44
- return this.addListener( this.requeststream, this.getRequestCallback( callback ), this.service )
45
- }
46
-
47
- getRequestCallback( callback:Function ){
48
- return async ( id:string, parameters:DecypheredParameters ) => {
49
- const result = await callback( id, parameters )
50
- if( !parameters.messageid ) return null
51
- const channel = this.getRequestSubscriptionName(parameters.messageid)
52
- return this.publish( channel, result )
53
- }
54
- }
55
-
56
- publish( channel:string, result:string ){
57
- return this.writer.publish( channel, result )
58
- }
59
-
60
- addListener( stream:string, callback:Function, group ?: string){
61
- const client = new IORedis( this.redisConfig.REDISURL as string )
62
- this.listeners.set( stream, new Listener( this, client, stream, callback, group ))
63
- return this
64
- }
65
-
66
- addListListener( event:string, callback:Function ){
67
- const client = new IORedis( this.redisConfig.REDISURL as string )
68
- const channel = this.getListChannel( event )
69
- this.listeners.set( channel, new ListListener( this, client, channel, callback ))
70
-
71
- return this
72
- }
73
-
74
- throwError( error:Error ){
75
- if(!this.rollbar) throw new Error('Rollbar not initialized')
76
- this.rollbar.error( error )
77
- }
78
-
79
- sendMessage( stream:string, data:Struct){
80
- return this.writer.xadd( stream, '*', ...this.createRedisMessage( data ))
81
- }
82
-
83
- async getRequest( targetservice:string, key:string, data:Struct ){
84
- // create a message id to subscribe to
85
- const messageid = uuidv4()
86
-
87
- //subscribe to message response
88
- const channel = this.getRequestSubscriptionName(messageid)
89
- await this.subscribe( channel )
90
-
91
- // send the message to the correct service
92
- this.sendMessage( this.getRequestStream(targetservice), {
93
- request : key,
94
- messageid : messageid,
95
- data : data
96
- })
97
-
98
- let resolver
99
- // create a promise to be able to pass on to resolve later
100
- const promise = new Promise((r) => {
101
- resolver = r
102
- })
103
-
104
- if( !resolver ) return null
105
-
106
- //setup a timeout
107
- const timeout = this.setupTimeout( resolver, channel )
108
-
109
- //setup a response
110
- this.requestMessageResponse( resolver, timeout )
111
-
112
- // return a promise that will resolve when the message returns or times out
113
- return promise
114
-
115
- }
116
-
117
- requestMessageResponse( resolve:(value?: any) => void, timeout:NodeJS.Timeout ){
118
- this.reader.once( 'message', (channel,message) => {
119
-
120
- if( message.length ) resolve( message );
121
- else resolve( null )
122
-
123
- this.unsubscribe( channel )
124
- clearTimeout( timeout )
125
-
126
- })
127
- }
128
-
129
- unsubscribe( channel:string ){
130
- this.reader.unsubscribe( channel )
131
- this.subscriptions = this.subscriptions.filter( s => s != channel )
132
- }
133
-
134
- setupTimeout( resolve:(value?: any) => void, channel:string, n:number = 2000 ){
135
- return setTimeout( () => {
136
- if( !this.subscriptions.includes( channel )) return
137
-
138
- console.log( `sub timedout: ${channel}`)
139
- resolve( null )
140
- this.unsubscribe( channel )
141
- }, n )
142
- }
143
-
144
- subscribe( channel:string ){
145
- this.subscriptions.push( channel )
146
- return this.reader.subscribe( channel )
147
- }
148
-
149
- getRequestSubscriptionName( messageid:string ){
150
- return `messageresponse${messageid}`
151
- }
152
-
153
- async sendListEvent( event:string, listitems:any[], data:Struct = {} ){
154
- const list = await this.addToList.call( this, listitems )
155
- return this.sendMessage(
156
- this.getListChannel( event ) , {
157
- ...data,
158
- listname : list
159
- } )
160
- }
161
-
162
- async addToList( listitems:any[], listname ?: string ){
163
- const list = listname??uuidv4()
164
- await this.writer.lpush( list , ...listitems.map( this.sanitizeValue) )
165
- return list
166
- }
167
-
168
- getListChannel( event:string ){
169
- return `${this.listprefix}${event}`
170
- }
171
-
172
- sanitizeValue( value:any ){
173
- if( isMap( value )) return stringifyMap( value )
174
- if( isObject( value )) return JSON.stringify( value )
175
- if( isArray( value )) return JSON.stringify( value )
176
- return value
177
- }
178
-
179
- createRedisMessage( struct:Struct ){
180
- return Object.keys( struct ).reduce( (arr:string[],key:keyof Struct) => [...arr,key,this.sanitizeValue( struct[key] )] , [] )
181
- }
182
-
183
- async getStreamMessages( stream:string ){
184
- const streaminfo = await this.getStreamInfo.call( this, stream )
185
- if( !streaminfo || !isArray( streaminfo ) || streaminfo.length < 10 ) return []
186
- const streamresponses = streaminfo[9] as StreamResponse[]
187
- return this.decypherResponse( ...streamresponses ).flatMap( r => r.messages )
188
- }
189
-
190
- getStreamInfo( stream:string, count:number = 0 ){
191
- return this.reader.xinfo('STREAM', stream ,'FULL', 'COUNT', count ) as Promise< null | any[]>
192
- }
193
-
194
- async filterStream( stream:string, key : string, value:any ){
195
- const messages = await this.getStreamMessages.call( this, stream )
196
- return messages.filter( message => message.parameters?.[key] != null && message.parameters[key] == value )
197
- }
198
-
199
- decypherResponse( ...responses:StreamResponse[] ):DecypheredResponse[]{
200
- return responses.reduce( (resp:DecypheredResponse[], response:StreamResponse) =>
201
- [
202
- ...resp,
203
- {
204
- stream : response[0],
205
- messages : response[1].map( (message) => ({
206
- id : message[0],
207
- parameters : this.decypherParameters( message[1] )
208
- }) as DecypheredMessage )
209
- } as DecypheredResponse
210
- ]
211
- , [] as DecypheredResponse[] )
212
- }
213
-
214
-
215
- decypherParameters( parameters:string[] ):DecypheredParameters{
216
- return parameters.reduce( ( params, v:string, n:number ) => ( n == 0 || ( n % 2 == 0)) && parameters.length >= n+1 ? ({
217
- ...params,
218
- [v] : parameters[n+1]
219
- }) : params , {} as DecypheredParameters)
220
- }
221
-
222
- }
223
-
224
-
@@ -1,63 +0,0 @@
1
- import { Redis } from "ioredis"
2
- import Broker from "./Broker"
3
-
4
- export default abstract class BrokerClient{
5
- broker : Broker
6
- client : Redis
7
- group : string | null = null
8
- stream : string | null = null
9
- list : string | null = null
10
- callback:Function
11
-
12
- constructor( broker:Broker, client:Redis, callback:Function, list:string | null, stream:string | null = null, group: string | null = null ){
13
- this.broker = broker
14
- this.client = client
15
- this.list = list
16
- this.stream = stream
17
- this.group = group
18
- this.callback = callback
19
-
20
- this.listenToStream.call( this )
21
- }
22
-
23
- throwError( error:any ){
24
- return this.broker.throwError( error )
25
- }
26
-
27
- decypherResponse( ...responses:StreamResponse[] ):DecypheredResponse[]{
28
- return this.broker.decypherResponse( ...responses )
29
- }
30
-
31
- async getGroupResponse():Promise< StreamResponse[] | null >{
32
- if( !this.group || !this.stream ) return null
33
- return await this.client.xreadgroup( 'GROUP', this.group, this.broker.consumername, 'COUNT', 1, 'BLOCK', 0, 'STREAMS', this.stream, '>' ) as StreamResponse[]
34
- }
35
-
36
- async getResponse( lastid:string ):Promise< StreamResponse[] | null >{
37
- if( !this.stream ) return null
38
- return await this.client.xread("BLOCK", 0, "STREAMS", this.stream, lastid )
39
- }
40
-
41
-
42
- async listenToStream( lastid:string = '$'):Promise<Function | null>{
43
- const responses = await this.getResponse.call( this, lastid )
44
- if( !responses ) return null
45
-
46
- const streamResponses = this.decypherResponse( ...responses )
47
- const messages = streamResponses.flatMap( r => r.messages )
48
- await Promise.all( messages.map( async (message) => {
49
- try{
50
- await this.streamCallback( message )
51
-
52
- }catch( e:any ){
53
- this.broker.throwError( e )
54
- }finally{
55
-
56
- }
57
- }) )
58
-
59
- return this.listenToStream.call( this, messages[messages.length-1]?.id??'$' )
60
- }
61
-
62
- abstract streamCallback( message:DecypheredMessage ):Promise<any | null>
63
- }
@@ -1,19 +0,0 @@
1
- import { Redis } from "ioredis"
2
- import Broker from "./Broker"
3
- import BrokerClient from "./BrokerClient"
4
- import ListRunner from "./ListRunner"
5
-
6
- export default class Listener extends BrokerClient{
7
- constructor( broker:Broker, client:Redis, list:string, callback:Function ){
8
- super( broker, client, callback, list )
9
- }
10
-
11
- async streamCallback( message:DecypheredMessage ){
12
- const listrunnercallback = await this.callback( message.id, message.parameters )
13
-
14
- if( message.parameters.listname )
15
- return new ListRunner( this.client, message.parameters.listname, listrunnercallback)
16
-
17
- return null
18
- }
19
- }
@@ -1,43 +0,0 @@
1
- import { Redis } from "ioredis"
2
-
3
- export default class ListRunner{
4
- listname:string
5
- itemsDone:number = 0
6
- itemsPerCall:number
7
- callback:Function
8
- client : Redis
9
-
10
-
11
- constructor( client:Redis, listname:string, callback:Function, itemsPerCall : number = 1 ){
12
- this.client = client
13
- this.callback = callback
14
- this.listname = listname
15
- this.itemsPerCall = itemsPerCall
16
-
17
- this.run.call( this )
18
- }
19
-
20
-
21
- async run():Promise<Function|void>{
22
- const items = await this.nextitems.call( this, this.listname )
23
- if( !items ){
24
- console.log( `finished with ${this.itemsDone} jobs`)
25
- return
26
- }
27
-
28
- try{
29
- await this.callback( items )
30
- }catch( e:any ){
31
- console.log( e )
32
-
33
- }finally{
34
- this.itemsDone += this.itemsPerCall
35
- return this.run.call( this )
36
- }
37
- }
38
-
39
- async nextitems( listname:string ):Promise<string[] | null>{
40
- return this.client.lpop( listname, this.itemsPerCall )
41
- }
42
-
43
- }
@@ -1,13 +0,0 @@
1
- import { Redis } from "ioredis"
2
- import Broker from "./Broker"
3
- import BrokerClient from "./BrokerClient"
4
-
5
- export default class Listener extends BrokerClient{
6
- constructor( broker:Broker, client:Redis, stream:string, callback:Function, group ?: string ){
7
- super( broker, client, callback, null, stream, group )
8
- }
9
-
10
- streamCallback(message: DecypheredMessage): Promise<any> {
11
- return this.callback( message.id, message.parameters )
12
- }
13
- }
package/src/main.ts DELETED
@@ -1,3 +0,0 @@
1
- import Broker from "./classes/Broker"
2
-
3
- export { Broker }
@@ -1,51 +0,0 @@
1
-
2
- const isJSON = ( str:any ) => {
3
- if( typeof str == 'number' ) return false
4
- try{
5
- JSON.parse( str )
6
- }catch( error ){
7
- return false;
8
- }
9
- return true;
10
- }
11
-
12
- interface ObjectToOmitFrom{
13
- [index: string]: any;
14
- }
15
-
16
-
17
- const omit = ( objectToOmitFrom:ObjectToOmitFrom, keys:(keyof ObjectToOmitFrom)[]) =>
18
- Object.keys( objectToOmitFrom )
19
- .filter( key => keys.indexOf( key ) == -1 )
20
- .reduce( (struct:object,key) =>
21
- Object.assign( struct, {[key]:objectToOmitFrom[key]} ) ,
22
- {}
23
- )
24
-
25
-
26
-
27
- const mapJsonReplacer = ( _key:any, value:Map<any,any> | any ) => {
28
- if(value instanceof Map) {
29
- return {
30
- dataType: 'Map',
31
- value: Array.from(value.entries()), // or with spread: value: [...value]
32
- } as JsonStringifiedMap
33
- } else {
34
- return value;
35
- }
36
- }
37
-
38
- const mapJsonReviver = ( _key:any, value:JsonStringifiedMap | any ) => {
39
- if(typeof value === 'object' && value !== null) {
40
- if (value.dataType === 'Map') {
41
- return new Map(value.value);
42
- }
43
- }
44
- return value;
45
- }
46
-
47
- const stringifyMap = ( map:Map<any,any> ):string=> JSON.stringify( map, exports.mapJsonReplacer)
48
- const parseMap = ( json:string ):Map<any,any> => JSON.parse( json, exports.mapJsonReviver)
49
- const capitalizeFirstLetter = (string:string) => string.charAt(0).toUpperCase() + string.slice(1)
50
-
51
- export { isJSON, omit, mapJsonReviver, stringifyMap, parseMap, mapJsonReplacer, capitalizeFirstLetter }