@sera4/essentia 1.0.25 → 1.0.27
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 +92 -4
- package/queue/publisher.js +4 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sera4/essentia",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.27",
|
|
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
|
|
|
@@ -15,6 +16,38 @@ class S4Queue {
|
|
|
15
16
|
this.subs = {};
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Opens a connection and immediately closes it.
|
|
21
|
+
* To be used for health checks.
|
|
22
|
+
* @param {Object} options Connection parameters. At the very least options.connectionUrl must be present.
|
|
23
|
+
*/
|
|
24
|
+
async testConnection(options) {
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
// We may run into issues with SNI TLS if
|
|
27
|
+
// we host with 3rd parties using our own certs.
|
|
28
|
+
// To avoid any issues, let's parse the url
|
|
29
|
+
// and provide the server name in the socket options
|
|
30
|
+
const urlParts = urlParse(options.connectionUrl);
|
|
31
|
+
const socketOptions = {servername: urlParts.hostname};
|
|
32
|
+
|
|
33
|
+
amqp.connect(options.connectionUrl, socketOptions, (err, conn) => {
|
|
34
|
+
if (err) {
|
|
35
|
+
return reject(err);
|
|
36
|
+
}
|
|
37
|
+
if (!conn) {
|
|
38
|
+
return reject("Failed to obtain connection");
|
|
39
|
+
}
|
|
40
|
+
conn.close(e => {
|
|
41
|
+
if (e) {
|
|
42
|
+
reject(e)
|
|
43
|
+
} else {
|
|
44
|
+
resolve(true)
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
18
51
|
/**
|
|
19
52
|
* Opens a connection to AMQP server.
|
|
20
53
|
* @param {Object} options Connection parameters. At the very least options.connectionUrl must be present.
|
|
@@ -37,7 +70,14 @@ class S4Queue {
|
|
|
37
70
|
// when a callback isn't provided, therefore run
|
|
38
71
|
// in a new Promise
|
|
39
72
|
return new Promise((resolve, reject) => {
|
|
40
|
-
|
|
73
|
+
// We may run into issues with SNI TLS if
|
|
74
|
+
// we host with 3rd parties using our own certs.
|
|
75
|
+
// To avoid any issues, let's parse the url
|
|
76
|
+
// and provide the server name in the socket options
|
|
77
|
+
const urlParts = urlParse(options.connectionUrl);
|
|
78
|
+
const socketOptions = {servername: urlParts.hostname};
|
|
79
|
+
|
|
80
|
+
amqp.connect(options.connectionUrl, socketOptions, (err, conn) => {
|
|
41
81
|
|
|
42
82
|
if (err) {
|
|
43
83
|
return reject(err);
|
|
@@ -123,6 +163,22 @@ class S4Queue {
|
|
|
123
163
|
this.pubs[name] = p;
|
|
124
164
|
}
|
|
125
165
|
|
|
166
|
+
/**
|
|
167
|
+
* Registers a new topic publisher on the given exchange.
|
|
168
|
+
* If exchange doesn't exist, one will be created.
|
|
169
|
+
* @param {String} exchange the name of the exchange on AMQP service.
|
|
170
|
+
*/
|
|
171
|
+
async registerTopicPublisher(exchange) {
|
|
172
|
+
const name = exchange;
|
|
173
|
+
if (Object.keys(this.pubs).includes(name)) {
|
|
174
|
+
throw new Error(`Publisher ${name} already registered`);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const p = new Publisher(exchange, 'topic', true, name);
|
|
178
|
+
await p.init(this.connection);
|
|
179
|
+
this.pubs[name] = p;
|
|
180
|
+
}
|
|
181
|
+
|
|
126
182
|
/**
|
|
127
183
|
* Registers a new direct subscriber on a given exchange and queue.
|
|
128
184
|
* If exchange and queue don't exists, they'll be created
|
|
@@ -152,15 +208,15 @@ class S4Queue {
|
|
|
152
208
|
const p = this.pubs[exchange];
|
|
153
209
|
|
|
154
210
|
if (!key) {
|
|
155
|
-
|
|
211
|
+
throw(new Error(`Direct message require a key`));
|
|
156
212
|
}
|
|
157
213
|
|
|
158
214
|
if (!p) {
|
|
159
|
-
|
|
215
|
+
throw(new Error(`No PUB for ${exchange} found`));
|
|
160
216
|
}
|
|
161
217
|
|
|
162
218
|
if (p.type !== 'direct') {
|
|
163
|
-
|
|
219
|
+
throw(new Error(`PUB ${exchange} is not direct`));
|
|
164
220
|
}
|
|
165
221
|
|
|
166
222
|
let content = msg;
|
|
@@ -174,6 +230,38 @@ class S4Queue {
|
|
|
174
230
|
return await p.publish({key, content});
|
|
175
231
|
}
|
|
176
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Publishes a message on a given exchange with a topic.
|
|
235
|
+
* @param {String} exchange the name of the exchange.
|
|
236
|
+
* @param {String} topic the name of the topic.
|
|
237
|
+
* @param {Object} msg a JSON object as the message.
|
|
238
|
+
*/
|
|
239
|
+
async publishTopicMessage(exchange, topic, msg) {
|
|
240
|
+
const p = this.pubs[exchange];
|
|
241
|
+
|
|
242
|
+
if (!topic) {
|
|
243
|
+
throw(new Error(`Topic message require a topic`));
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (!p) {
|
|
247
|
+
throw(new Error(`No PUB for ${exchange} found`));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (p.type !== 'topic') {
|
|
251
|
+
throw(new Error(`PUB ${exchange} is not topic`));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
let content = msg;
|
|
255
|
+
if (content.constructor !== ({}).constructor) {
|
|
256
|
+
// if not in JSON format, let's make it so
|
|
257
|
+
content = {
|
|
258
|
+
msg: msg
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return await p.publish({key: topic, content});
|
|
263
|
+
}
|
|
264
|
+
|
|
177
265
|
/**
|
|
178
266
|
* Adds a listener for a specific key.
|
|
179
267
|
* 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});
|