redis-consumer 1.1.5 → 1.1.7
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/dist/consumer.js +138 -144
- package/package.json +3 -3
package/dist/consumer.js
CHANGED
|
@@ -3,160 +3,154 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.RedisConsumer = void 0;
|
|
4
4
|
const retry_processor_1 = require("./retry-processor");
|
|
5
5
|
class RedisConsumer {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
6
|
+
client;
|
|
7
|
+
originalClient;
|
|
8
|
+
state;
|
|
9
|
+
retryProcessor;
|
|
10
|
+
successfullMessages = new Map();
|
|
11
|
+
BLOCK;
|
|
12
|
+
COUNT;
|
|
13
|
+
RETRIES;
|
|
14
|
+
constructor(client, options = {}) {
|
|
15
|
+
this.originalClient = client;
|
|
16
|
+
this.client = client.duplicate();
|
|
17
|
+
this.state = {};
|
|
18
|
+
this.COUNT = options.COUNT ?? 1;
|
|
19
|
+
this.BLOCK = options.BLOCK ?? 0;
|
|
20
|
+
this.RETRIES = options.retries ?? 3;
|
|
21
|
+
this.retryProcessor = new retry_processor_1.RetryProcessor(this, {
|
|
22
|
+
retryTime: options.retryTime,
|
|
23
|
+
maxRetry: this.RETRIES,
|
|
24
|
+
});
|
|
25
|
+
this.client.connect();
|
|
26
|
+
}
|
|
27
|
+
set block(block) {
|
|
28
|
+
this.BLOCK = block;
|
|
29
|
+
}
|
|
30
|
+
set count(count) {
|
|
31
|
+
this.COUNT = count;
|
|
32
|
+
}
|
|
33
|
+
set retries(retries) {
|
|
34
|
+
this.RETRIES = retries;
|
|
35
|
+
}
|
|
36
|
+
get settings() {
|
|
37
|
+
return { block: this.BLOCK, count: this.COUNT };
|
|
38
|
+
}
|
|
39
|
+
async listen(streams) {
|
|
40
|
+
if (!Array.isArray(streams)) {
|
|
41
|
+
streams = [streams];
|
|
26
42
|
}
|
|
27
|
-
|
|
28
|
-
|
|
43
|
+
for (const stream of streams) {
|
|
44
|
+
const groupExists = await this.originalClient.groupExists(stream.name);
|
|
45
|
+
if (!groupExists) {
|
|
46
|
+
await this.originalClient.createGroup(stream.name);
|
|
47
|
+
}
|
|
48
|
+
if (this.hasStreamState(stream.name)) continue;
|
|
49
|
+
this.initStreamState(stream);
|
|
29
50
|
}
|
|
30
|
-
|
|
31
|
-
|
|
51
|
+
this.listenForStreams();
|
|
52
|
+
}
|
|
53
|
+
addAckMessage(stream, id) {
|
|
54
|
+
if (this.successfullMessages.has(stream)) {
|
|
55
|
+
const ackMessages = this.successfullMessages.get(stream);
|
|
56
|
+
ackMessages.push(id);
|
|
57
|
+
} else {
|
|
58
|
+
this.successfullMessages.set(stream, [id]);
|
|
32
59
|
}
|
|
33
|
-
|
|
34
|
-
|
|
60
|
+
}
|
|
61
|
+
async listenForStreams() {
|
|
62
|
+
const state = this.state;
|
|
63
|
+
const streamsToListen = [];
|
|
64
|
+
for (const stream in state) {
|
|
65
|
+
streamsToListen.push({ key: stream, id: state[stream].nextId });
|
|
35
66
|
}
|
|
36
|
-
|
|
37
|
-
|
|
67
|
+
const streamsMessages = await this.readStreams(streamsToListen);
|
|
68
|
+
if (!streamsMessages) {
|
|
69
|
+
await this.acknowlegdeMessages();
|
|
70
|
+
this.listenForStreams();
|
|
71
|
+
return;
|
|
38
72
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
streams = [streams];
|
|
42
|
-
}
|
|
43
|
-
for (const stream of streams) {
|
|
44
|
-
const groupExists = await this.originalClient.groupExists(stream.name);
|
|
45
|
-
if (!groupExists) {
|
|
46
|
-
await this.originalClient.createGroup(stream.name);
|
|
47
|
-
}
|
|
48
|
-
if (this.hasStreamState(stream.name))
|
|
49
|
-
continue;
|
|
50
|
-
this.initStreamState(stream);
|
|
51
|
-
}
|
|
52
|
-
this.listenForStreams();
|
|
53
|
-
}
|
|
54
|
-
addAckMessage(stream, id) {
|
|
55
|
-
if (this.successfullMessages.has(stream)) {
|
|
56
|
-
const ackMessages = this.successfullMessages.get(stream);
|
|
57
|
-
ackMessages.push(id);
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
this.successfullMessages.set(stream, [id]);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
async listenForStreams() {
|
|
64
|
-
const state = this.state;
|
|
65
|
-
const streamsToListen = [];
|
|
66
|
-
for (const stream in state) {
|
|
67
|
-
streamsToListen.push({ key: stream, id: state[stream].nextId });
|
|
68
|
-
}
|
|
69
|
-
const streamsMessages = await this.readStreams(streamsToListen);
|
|
70
|
-
if (!streamsMessages) {
|
|
71
|
-
await this.acknowlegdeMessages();
|
|
72
|
-
this.listenForStreams();
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
for (const streamMessages of streamsMessages) {
|
|
76
|
-
await this.processStreamMessages(streamMessages);
|
|
77
|
-
}
|
|
78
|
-
this.listenForStreams();
|
|
73
|
+
for (const streamMessages of streamsMessages) {
|
|
74
|
+
await this.processStreamMessages(streamMessages);
|
|
79
75
|
}
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
this.listenForStreams();
|
|
77
|
+
}
|
|
78
|
+
hasStreamState(name) {
|
|
79
|
+
return !!this.getStreamState(name);
|
|
80
|
+
}
|
|
81
|
+
getStreamState(name) {
|
|
82
|
+
return this.state[name];
|
|
83
|
+
}
|
|
84
|
+
initStreamState(stream) {
|
|
85
|
+
const name = stream.name;
|
|
86
|
+
const executable = stream.executable;
|
|
87
|
+
let lastSuccessId;
|
|
88
|
+
if (stream.id) {
|
|
89
|
+
lastSuccessId = stream.id;
|
|
90
|
+
} else {
|
|
91
|
+
lastSuccessId = "0-0";
|
|
82
92
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
93
|
+
let nextId = lastSuccessId;
|
|
94
|
+
this.state[name] = { nextId, lastSuccessId, executable, recovering: true };
|
|
95
|
+
}
|
|
96
|
+
async readStreams(streamsToListen) {
|
|
97
|
+
const messages = await this.client.xReadGroup(
|
|
98
|
+
this.originalClient.groupName,
|
|
99
|
+
this.originalClient.clientName,
|
|
100
|
+
streamsToListen,
|
|
101
|
+
{ BLOCK: this.BLOCK, COUNT: this.COUNT },
|
|
102
|
+
);
|
|
103
|
+
return messages;
|
|
104
|
+
}
|
|
105
|
+
async processStreamMessages(streamMessages) {
|
|
106
|
+
const stream = streamMessages.name;
|
|
107
|
+
const state = this.getStreamState(stream);
|
|
108
|
+
if (!state)
|
|
109
|
+
throw new Error("No state was found for stream processing of " + stream);
|
|
110
|
+
const fnc = state.executable;
|
|
111
|
+
const messages = streamMessages.messages;
|
|
112
|
+
for (const message of messages) {
|
|
113
|
+
try {
|
|
114
|
+
await fnc(message, stream);
|
|
115
|
+
this.addAckMessage(stream, message.id);
|
|
116
|
+
} catch (err) {
|
|
117
|
+
// console.error(err);
|
|
118
|
+
this.client.emit("process-error", err, { stream, message, retries: 0 });
|
|
119
|
+
if (this.RETRIES === 0) continue;
|
|
120
|
+
if (err instanceof Error) {
|
|
121
|
+
this.retryProcessor.add(err, stream, message, fnc);
|
|
122
|
+
} else {
|
|
123
|
+
const newErr = new Error(String(err));
|
|
124
|
+
this.retryProcessor.add(newErr, stream, message, fnc);
|
|
90
125
|
}
|
|
126
|
+
}
|
|
91
127
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
let nextId = lastSuccessId;
|
|
103
|
-
this.state[name] = { nextId, lastSuccessId, executable, recovering: true };
|
|
128
|
+
await this.acknowlegdeMessages();
|
|
129
|
+
const recovering = state.recovering;
|
|
130
|
+
if (recovering && messages.length === 0) {
|
|
131
|
+
state.nextId = ">";
|
|
132
|
+
state.recovering = false;
|
|
133
|
+
} else if (recovering) {
|
|
134
|
+
const lastMessage = messages.slice(-1);
|
|
135
|
+
const lastId = lastMessage[0].id;
|
|
136
|
+
state.nextId = lastId;
|
|
104
137
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
try {
|
|
121
|
-
await fnc(message, stream);
|
|
122
|
-
this.addAckMessage(stream, message.id);
|
|
123
|
-
}
|
|
124
|
-
catch (err) {
|
|
125
|
-
this.client.emit('process-error', err, { stream, message, retries: 0 });
|
|
126
|
-
if (this.RETRIES === 0)
|
|
127
|
-
continue;
|
|
128
|
-
if (err instanceof Error) {
|
|
129
|
-
this.retryProcessor.add(err, stream, message, fnc);
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
const newErr = new Error(String(err));
|
|
133
|
-
this.retryProcessor.add(newErr, stream, message, fnc);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
await this.acknowlegdeMessages();
|
|
138
|
-
const recovering = state.recovering;
|
|
139
|
-
if (recovering && messages.length === 0) {
|
|
140
|
-
state.nextId = '>';
|
|
141
|
-
state.recovering = false;
|
|
142
|
-
}
|
|
143
|
-
else if (recovering) {
|
|
144
|
-
const lastMessage = messages.slice(-1);
|
|
145
|
-
const lastId = lastMessage[0].id;
|
|
146
|
-
state.nextId = lastId;
|
|
147
|
-
}
|
|
148
|
-
return true;
|
|
149
|
-
}
|
|
150
|
-
async acknowlegdeMessages() {
|
|
151
|
-
for (const item of this.successfullMessages) {
|
|
152
|
-
const stream = item[0];
|
|
153
|
-
const ackMessages = item[1];
|
|
154
|
-
const id = await this.originalClient.xAck(stream, this.originalClient.groupName, ackMessages);
|
|
155
|
-
if (id) {
|
|
156
|
-
this.successfullMessages.delete(stream);
|
|
157
|
-
await this.originalClient.xDel(stream, ackMessages);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
async acknowlegdeMessages() {
|
|
141
|
+
for (const item of this.successfullMessages) {
|
|
142
|
+
const stream = item[0];
|
|
143
|
+
const ackMessages = item[1];
|
|
144
|
+
const id = await this.originalClient.xAck(
|
|
145
|
+
stream,
|
|
146
|
+
this.originalClient.groupName,
|
|
147
|
+
ackMessages,
|
|
148
|
+
);
|
|
149
|
+
if (id) {
|
|
150
|
+
await this.originalClient.xDel(stream, ackMessages);
|
|
151
|
+
this.successfullMessages.delete(stream);
|
|
152
|
+
}
|
|
160
153
|
}
|
|
154
|
+
}
|
|
161
155
|
}
|
|
162
156
|
exports.RedisConsumer = RedisConsumer;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "redis-consumer",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.7",
|
|
4
4
|
"description": "Simple NodeJs consumer and producer for Redis Streams",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
},
|
|
34
34
|
"homepage": "https://github.com/tomasky/redis-streams-nodejs#readme",
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"redis": "^
|
|
36
|
+
"redis": "^5.0.1"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@types/node": "^
|
|
39
|
+
"@types/node": "^22.15.0",
|
|
40
40
|
"typescript": "latest"
|
|
41
41
|
}
|
|
42
42
|
}
|