@sera4/essentia 1.0.24 → 1.0.26
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/package.json +2 -1
- package/package.tar.gz +0 -0
- package/queue/index.js +60 -4
- package/queue/publisher.js +4 -2
- package/queue/subscriber.js +9 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sera4/essentia",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.26",
|
|
4
4
|
"description": "A library of utilities for Teleporte Web Services",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"async": "^2.6.1",
|
|
30
30
|
"fast-safe-stringify": "^2.0.6",
|
|
31
31
|
"git-rev": "^0.2.1",
|
|
32
|
+
"url-parse": "^1.4.7",
|
|
32
33
|
"uuid": "^3.3.3",
|
|
33
34
|
"winston": "^3.2.1",
|
|
34
35
|
"winston-logstash": "^0.4.0"
|
package/package.tar.gz
CHANGED
|
Binary file
|
package/queue/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const amqp = require("amqplib/callback_api");
|
|
3
3
|
const logger = require("./queue-logger");
|
|
4
|
+
const urlParse = require("url-parse");
|
|
4
5
|
const { Publisher } = require("./publisher");
|
|
5
6
|
const { Subscriber } = require("./subscriber");
|
|
6
7
|
|
|
@@ -37,7 +38,14 @@ class S4Queue {
|
|
|
37
38
|
// when a callback isn't provided, therefore run
|
|
38
39
|
// in a new Promise
|
|
39
40
|
return new Promise((resolve, reject) => {
|
|
40
|
-
|
|
41
|
+
// We may run into issues with SNI TLS if
|
|
42
|
+
// we host with 3rd parties using our own certs.
|
|
43
|
+
// To avoid any issues, let's parse the url
|
|
44
|
+
// and provide the server name in the socket options
|
|
45
|
+
const urlParts = urlParse(options.connectionUrl);
|
|
46
|
+
const socketOptions = {servername: urlParts.hostname};
|
|
47
|
+
|
|
48
|
+
amqp.connect(options.connectionUrl, socketOptions, (err, conn) => {
|
|
41
49
|
|
|
42
50
|
if (err) {
|
|
43
51
|
return reject(err);
|
|
@@ -123,6 +131,22 @@ class S4Queue {
|
|
|
123
131
|
this.pubs[name] = p;
|
|
124
132
|
}
|
|
125
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Registers a new topic publisher on the given exchange.
|
|
136
|
+
* If exchange doesn't exist, one will be created.
|
|
137
|
+
* @param {String} exchange the name of the exchange on AMQP service.
|
|
138
|
+
*/
|
|
139
|
+
async registerTopicPublisher(exchange) {
|
|
140
|
+
const name = exchange;
|
|
141
|
+
if (Object.keys(this.pubs).includes(name)) {
|
|
142
|
+
throw new Error(`Publisher ${name} already registered`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const p = new Publisher(exchange, 'topic', true, name);
|
|
146
|
+
await p.init(this.connection);
|
|
147
|
+
this.pubs[name] = p;
|
|
148
|
+
}
|
|
149
|
+
|
|
126
150
|
/**
|
|
127
151
|
* Registers a new direct subscriber on a given exchange and queue.
|
|
128
152
|
* If exchange and queue don't exists, they'll be created
|
|
@@ -152,15 +176,15 @@ class S4Queue {
|
|
|
152
176
|
const p = this.pubs[exchange];
|
|
153
177
|
|
|
154
178
|
if (!key) {
|
|
155
|
-
|
|
179
|
+
throw(new Error(`Direct message require a key`));
|
|
156
180
|
}
|
|
157
181
|
|
|
158
182
|
if (!p) {
|
|
159
|
-
|
|
183
|
+
throw(new Error(`No PUB for ${exchange} found`));
|
|
160
184
|
}
|
|
161
185
|
|
|
162
186
|
if (p.type !== 'direct') {
|
|
163
|
-
|
|
187
|
+
throw(new Error(`PUB ${exchange} is not direct`));
|
|
164
188
|
}
|
|
165
189
|
|
|
166
190
|
let content = msg;
|
|
@@ -174,6 +198,38 @@ class S4Queue {
|
|
|
174
198
|
return await p.publish({key, content});
|
|
175
199
|
}
|
|
176
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Publishes a message on a given exchange with a topic.
|
|
203
|
+
* @param {String} exchange the name of the exchange.
|
|
204
|
+
* @param {String} topic the name of the topic.
|
|
205
|
+
* @param {Object} msg a JSON object as the message.
|
|
206
|
+
*/
|
|
207
|
+
async publishTopicMessage(exchange, topic, msg) {
|
|
208
|
+
const p = this.pubs[exchange];
|
|
209
|
+
|
|
210
|
+
if (!topic) {
|
|
211
|
+
throw(new Error(`Topic message require a topic`));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (!p) {
|
|
215
|
+
throw(new Error(`No PUB for ${exchange} found`));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (p.type !== 'topic') {
|
|
219
|
+
throw(new Error(`PUB ${exchange} is not topic`));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
let content = msg;
|
|
223
|
+
if (content.constructor !== ({}).constructor) {
|
|
224
|
+
// if not in JSON format, let's make it so
|
|
225
|
+
content = {
|
|
226
|
+
msg: msg
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return await p.publish({key: topic, content});
|
|
231
|
+
}
|
|
232
|
+
|
|
177
233
|
/**
|
|
178
234
|
* Adds a listener for a specific key.
|
|
179
235
|
* If a subscriber that was regitered was found
|
package/queue/publisher.js
CHANGED
|
@@ -27,7 +27,7 @@ class Publisher {
|
|
|
27
27
|
* @param {Object} conn amqp connection object
|
|
28
28
|
*/
|
|
29
29
|
async init (conn) {
|
|
30
|
-
logger.debug(`Initializing PUB channel for ${this.name}`);
|
|
30
|
+
logger.debug(`Initializing PUB channel for ${this.name}. Type: ${this.type}`);
|
|
31
31
|
|
|
32
32
|
if(this.channel) {
|
|
33
33
|
logger.warn(`PUB channel for ${this.name} already initialized`);
|
|
@@ -67,7 +67,9 @@ class Publisher {
|
|
|
67
67
|
tracking_id: uuidv4(),
|
|
68
68
|
data: msg.content
|
|
69
69
|
}
|
|
70
|
-
logger.debug("Publishing message"
|
|
70
|
+
logger.debug("Publishing message");
|
|
71
|
+
logger.debug("Key", msg.key);
|
|
72
|
+
logger.debug("Data", parcel);
|
|
71
73
|
|
|
72
74
|
const content = Buffer.from(JSON.stringify(parcel));
|
|
73
75
|
const res = await this.channel.publish(this.exchange, msg.key, content, {persistent: true});
|
package/queue/subscriber.js
CHANGED
|
@@ -63,11 +63,18 @@ class Subscriber {
|
|
|
63
63
|
|
|
64
64
|
this.channel.consume(this.queue, (msg) => {
|
|
65
65
|
const { fields, content } = msg;
|
|
66
|
-
|
|
66
|
+
let payload = null;
|
|
67
|
+
let error = null;
|
|
68
|
+
try {
|
|
69
|
+
payload = JSON.parse(content.toString());
|
|
70
|
+
} catch (e) {
|
|
71
|
+
logger.error("Failed to parse incomming message:", e);
|
|
72
|
+
error = e;
|
|
73
|
+
}
|
|
67
74
|
logger.debug(`Got message from exchange '${fields.exchange}' with key '${fields.routingKey}'`);
|
|
68
75
|
logger.debug("Content", payload);
|
|
69
76
|
this.callbacks.forEach(cb => {
|
|
70
|
-
cb(payload);
|
|
77
|
+
cb(payload, error);
|
|
71
78
|
});
|
|
72
79
|
this.channel.ack(msg);
|
|
73
80
|
}, { noAck: false });
|