@rxdi/rabbitmq-pubsub 0.7.118

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/.babelrc ADDED
@@ -0,0 +1,4 @@
1
+
2
+ {
3
+ "presets": ["es2015", "stage-0", "stage-2"]
4
+ }
package/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ language: node_js
2
+ node_js:
3
+ - "6"
4
+ - "4"
5
+
6
+ cache:
7
+ directories:
8
+ - node_modules
9
+
10
+ install:
11
+ - npm install
12
+
13
+ services:
14
+ - redis-server
package/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # @rxdi/graphql-rabbitmq-pubsub
2
+ Hard Forked from [graphql-rabbitmq-subscriptions](https://github.com/cdmbase/rabbitmq-pubsub)
@@ -0,0 +1,10 @@
1
+ export declare function createChildLogger(logger: Logger, className: string): {
2
+ trace: (...message: any[]) => void;
3
+ error: (...message: any[]) => void;
4
+ debug: (...message: any[]) => void;
5
+ };
6
+ export interface Logger {
7
+ trace: (...m: any[]) => void;
8
+ error: (...m: any[]) => void;
9
+ debug: (...m: any[]) => void;
10
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createChildLogger = void 0;
4
+ function createChildLogger(logger, className) {
5
+ return {
6
+ trace: (...message) => process.env.PUBSUB_LOGGING && console.log(...message),
7
+ error: (...message) => process.env.PUBSUB_LOGGING && console.error(...message),
8
+ debug: (...message) => process.env.PUBSUB_LOGGING && console.log(...message),
9
+ };
10
+ }
11
+ exports.createChildLogger = createChildLogger;
@@ -0,0 +1,36 @@
1
+ export interface IQueueNameConfig {
2
+ /**
3
+ * Set the prefetch count for this channel.
4
+ * The count given is the maximum number of messages
5
+ * sent over the channel that can be awaiting acknowledgement
6
+ * once there are count messages outstanding,
7
+ * the server will not send more messages on this channel
8
+ * until one or more have been acknowledged.
9
+ * A falsey value for count indicates no such limit.
10
+ * https://www.squaremobius.net/amqp.node/channel_api.html#channel_prefetch
11
+ */
12
+ prefetch?: number;
13
+ /**
14
+ * If we set global to true we will apply prefetch count globally for the queue
15
+ * The count given is the maximum number of messages
16
+ */
17
+ globalPrefetch?: boolean;
18
+ name: string;
19
+ dlq: string;
20
+ dlx: string;
21
+ strictName?: boolean;
22
+ }
23
+ export declare class DefaultQueueNameConfig implements IQueueNameConfig {
24
+ name: string;
25
+ dlq: string;
26
+ dlx: string;
27
+ constructor(name: string);
28
+ }
29
+ export declare class DefaultPubSubQueueConfig implements IQueueNameConfig {
30
+ name: string;
31
+ dlq: string;
32
+ dlx: string;
33
+ constructor(name: string);
34
+ }
35
+ export declare function asQueueNameConfig(config: IQueueNameConfig | string): IQueueNameConfig;
36
+ export declare function asPubSubQueueNameConfig(config: IQueueNameConfig | string): IQueueNameConfig;
package/dist/common.js ADDED
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.asPubSubQueueNameConfig = exports.asQueueNameConfig = exports.DefaultPubSubQueueConfig = exports.DefaultQueueNameConfig = void 0;
4
+ class DefaultQueueNameConfig {
5
+ constructor(name) {
6
+ this.name = name;
7
+ this.dlq = `${name}.DLQ`;
8
+ this.dlx = `${this.dlq}.Exchange`;
9
+ }
10
+ }
11
+ exports.DefaultQueueNameConfig = DefaultQueueNameConfig;
12
+ class DefaultPubSubQueueConfig {
13
+ constructor(name) {
14
+ this.name = name;
15
+ this.dlq = "";
16
+ this.dlx = `${name}.DLQ.Exchange`;
17
+ }
18
+ }
19
+ exports.DefaultPubSubQueueConfig = DefaultPubSubQueueConfig;
20
+ function asQueueNameConfig(config) {
21
+ return isQueueNameConfig(config)
22
+ ? config
23
+ : new DefaultQueueNameConfig(config);
24
+ }
25
+ exports.asQueueNameConfig = asQueueNameConfig;
26
+ function asPubSubQueueNameConfig(config) {
27
+ return isQueueNameConfig(config)
28
+ ? config
29
+ : new DefaultPubSubQueueConfig(config);
30
+ }
31
+ exports.asPubSubQueueNameConfig = asPubSubQueueNameConfig;
32
+ function isQueueNameConfig(config) {
33
+ if (config.name &&
34
+ config.dlq &&
35
+ config.dlx) {
36
+ return true;
37
+ }
38
+ }
@@ -0,0 +1,23 @@
1
+ import * as amqp from "amqplib";
2
+ import { Logger } from "./childLogger";
3
+ export interface IRabbitMqConnectionFactory {
4
+ create(): Promise<amqp.Connection>;
5
+ }
6
+ export interface IRabbitMqConnectionConfig {
7
+ host: string;
8
+ port: number;
9
+ }
10
+ export declare class RabbitMqConnectionFactory implements IRabbitMqConnectionFactory {
11
+ private logger;
12
+ private connection;
13
+ connect: any;
14
+ constructor(logger: Logger, config: IRabbitMqConnectionConfig | string);
15
+ create(): Promise<amqp.Connection>;
16
+ }
17
+ export declare class RabbitMqSingletonConnectionFactory implements IRabbitMqConnectionFactory {
18
+ private logger;
19
+ private connection;
20
+ private promise;
21
+ constructor(logger: Logger, config: IRabbitMqConnectionConfig | string);
22
+ create(): Promise<amqp.Connection>;
23
+ }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RabbitMqSingletonConnectionFactory = exports.RabbitMqConnectionFactory = void 0;
4
+ const amqp = require("amqplib");
5
+ const childLogger_1 = require("./childLogger");
6
+ function isConnectionConfig(config) {
7
+ if (config.host &&
8
+ config.port) {
9
+ return true;
10
+ }
11
+ }
12
+ class RabbitMqConnectionFactory {
13
+ constructor(logger, config) {
14
+ this.logger = logger;
15
+ this.connection = isConnectionConfig(config)
16
+ ? `amqp://${config.host}:${config.port}`
17
+ : config;
18
+ this.logger = childLogger_1.createChildLogger(logger, "RabbitMqConnectionFactory");
19
+ }
20
+ create() {
21
+ this.logger.debug("connecting to %s", this.connection);
22
+ if (this.connect) {
23
+ return Promise.resolve(this.connect);
24
+ }
25
+ return Promise.resolve(amqp.connect(this.connection))
26
+ .then((connect) => {
27
+ this.connect = connect;
28
+ return connect;
29
+ })
30
+ .catch((err) => {
31
+ this.logger.error("failed to create connection '%s'", this.connection);
32
+ return Promise.reject(err);
33
+ });
34
+ }
35
+ }
36
+ exports.RabbitMqConnectionFactory = RabbitMqConnectionFactory;
37
+ class RabbitMqSingletonConnectionFactory {
38
+ constructor(logger, config) {
39
+ this.logger = logger;
40
+ this.connection = isConnectionConfig(config)
41
+ ? `amqp://${config.host}:${config.port}`
42
+ : config;
43
+ }
44
+ create() {
45
+ if (this.promise) {
46
+ this.logger.trace("reusing connection to %s", this.connection);
47
+ return this.promise;
48
+ }
49
+ this.logger.debug("creating connection to %s", this.connection);
50
+ return (this.promise = Promise.resolve(amqp.connect(this.connection)));
51
+ }
52
+ }
53
+ exports.RabbitMqSingletonConnectionFactory = RabbitMqSingletonConnectionFactory;
@@ -0,0 +1,19 @@
1
+ import * as amqp from "amqplib";
2
+ import { IRabbitMqConnectionFactory } from "./connectionFactory";
3
+ import { IQueueNameConfig } from "./common";
4
+ import { Logger } from "./childLogger";
5
+ export interface IRabbitMqConsumerDisposer {
6
+ (): Promise<unknown>;
7
+ }
8
+ export declare class RabbitMqConsumer {
9
+ private logger;
10
+ private connectionFactory;
11
+ constructor(logger: Logger, connectionFactory: IRabbitMqConnectionFactory);
12
+ subscribe<T>(queue: string | IQueueNameConfig, action: (message: T) => Promise<any> | void): Promise<IRabbitMqConsumerDisposer>;
13
+ private setupChannel;
14
+ private subscribeToChannel;
15
+ protected getMessageObject<T>(message: amqp.Message): T;
16
+ protected getChannelSetup(channel: amqp.Channel, queueConfig: IQueueNameConfig): import("bluebird")<amqp.Replies.Empty>[];
17
+ protected getQueueSettings(deadletterExchangeName: string): amqp.Options.AssertQueue;
18
+ protected getDLSettings(): amqp.Options.AssertQueue;
19
+ }
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RabbitMqConsumer = void 0;
13
+ const common_1 = require("./common");
14
+ const childLogger_1 = require("./childLogger");
15
+ class RabbitMqConsumer {
16
+ constructor(logger, connectionFactory) {
17
+ this.logger = logger;
18
+ this.connectionFactory = connectionFactory;
19
+ this.logger = childLogger_1.createChildLogger(logger, "RabbitMqConsumer");
20
+ }
21
+ subscribe(queue, action) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ const queueConfig = common_1.asQueueNameConfig(queue);
24
+ const connection = yield this.connectionFactory.create();
25
+ const channel = yield connection.createChannel();
26
+ this.logger.trace("got channel for queue '%s'", queueConfig.name);
27
+ yield this.setupChannel(channel, queueConfig);
28
+ return this.subscribeToChannel(channel, queueConfig, action);
29
+ });
30
+ }
31
+ setupChannel(channel, queueConfig) {
32
+ this.logger.trace("setup '%j'", queueConfig);
33
+ return Promise.all(this.getChannelSetup(channel, queueConfig));
34
+ }
35
+ subscribeToChannel(channel, queueConfig, action) {
36
+ return __awaiter(this, void 0, void 0, function* () {
37
+ this.logger.trace("subscribing to queue '%s'", queueConfig.name);
38
+ const opts = yield channel.consume(queueConfig.name, (message) => __awaiter(this, void 0, void 0, function* () {
39
+ let msg = this.getMessageObject(message);
40
+ this.logger.trace("message arrived from queue '%s' (%j)", queueConfig.name, msg);
41
+ try {
42
+ yield action(msg);
43
+ }
44
+ catch (err) {
45
+ this.logger.error(err, "message processing failed from queue '%j' (%j)", queueConfig, msg);
46
+ channel.nack(message, false, false);
47
+ return;
48
+ }
49
+ this.logger.trace("message processed from queue '%s' (%j)", queueConfig.name, msg);
50
+ channel.ack(message);
51
+ }));
52
+ this.logger.trace("subscribed to queue '%s' (%s)", queueConfig.name, opts.consumerTag);
53
+ return (() => __awaiter(this, void 0, void 0, function* () {
54
+ this.logger.trace("disposing subscriber to queue '%s' (%s)", queueConfig.name, opts.consumerTag);
55
+ yield channel.cancel(opts.consumerTag);
56
+ yield channel.close();
57
+ return Promise.resolve();
58
+ }));
59
+ });
60
+ }
61
+ getMessageObject(message) {
62
+ return JSON.parse(message.content.toString("utf8"));
63
+ }
64
+ getChannelSetup(channel, queueConfig) {
65
+ return [
66
+ channel.assertQueue(queueConfig.name, this.getQueueSettings(queueConfig.dlx)),
67
+ channel.assertQueue(queueConfig.dlq, this.getDLSettings()),
68
+ channel.assertExchange(queueConfig.dlx, "fanout", this.getDLSettings()),
69
+ channel.bindQueue(queueConfig.dlq, queueConfig.dlx, "*"),
70
+ ];
71
+ }
72
+ getQueueSettings(deadletterExchangeName) {
73
+ var settings = this.getDLSettings();
74
+ settings.arguments = {
75
+ "x-dead-letter-exchange": deadletterExchangeName,
76
+ };
77
+ return settings;
78
+ }
79
+ getDLSettings() {
80
+ return {
81
+ durable: true,
82
+ autoDelete: true,
83
+ };
84
+ }
85
+ }
86
+ exports.RabbitMqConsumer = RabbitMqConsumer;
@@ -0,0 +1,6 @@
1
+ export { IRabbitMqConnectionFactory, IRabbitMqConnectionConfig, RabbitMqConnectionFactory, RabbitMqSingletonConnectionFactory, } from "./connectionFactory";
2
+ export { RabbitMqConsumer, IRabbitMqConsumerDisposer } from "./consumer";
3
+ export { RabbitMqProducer } from "./producer";
4
+ export { RabbitMqPublisher } from "./publisher";
5
+ export { RabbitMqSubscriber, IRabbitMqSubscriberDisposer } from "./subscriber";
6
+ export { IQueueNameConfig } from "./common";
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var connectionFactory_1 = require("./connectionFactory");
4
+ Object.defineProperty(exports, "RabbitMqConnectionFactory", { enumerable: true, get: function () { return connectionFactory_1.RabbitMqConnectionFactory; } });
5
+ Object.defineProperty(exports, "RabbitMqSingletonConnectionFactory", { enumerable: true, get: function () { return connectionFactory_1.RabbitMqSingletonConnectionFactory; } });
6
+ var consumer_1 = require("./consumer");
7
+ Object.defineProperty(exports, "RabbitMqConsumer", { enumerable: true, get: function () { return consumer_1.RabbitMqConsumer; } });
8
+ var producer_1 = require("./producer");
9
+ Object.defineProperty(exports, "RabbitMqProducer", { enumerable: true, get: function () { return producer_1.RabbitMqProducer; } });
10
+ var publisher_1 = require("./publisher");
11
+ Object.defineProperty(exports, "RabbitMqPublisher", { enumerable: true, get: function () { return publisher_1.RabbitMqPublisher; } });
12
+ var subscriber_1 = require("./subscriber");
13
+ Object.defineProperty(exports, "RabbitMqSubscriber", { enumerable: true, get: function () { return subscriber_1.RabbitMqSubscriber; } });
@@ -0,0 +1,13 @@
1
+ /// <reference types="node" />
2
+ import * as amqp from "amqplib";
3
+ import { IRabbitMqConnectionFactory } from "./connectionFactory";
4
+ import { IQueueNameConfig } from "./common";
5
+ import { Logger } from "./childLogger";
6
+ export declare class RabbitMqProducer {
7
+ private logger;
8
+ private connectionFactory;
9
+ constructor(logger: Logger, connectionFactory: IRabbitMqConnectionFactory);
10
+ publish<T>(queue: string | IQueueNameConfig, message: T, options?: IQueueNameConfig): Promise<void>;
11
+ protected getMessageBuffer<T>(message: T): Buffer;
12
+ protected getQueueSettings(deadletterExchangeName: string): amqp.Options.AssertQueue;
13
+ }
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RabbitMqProducer = void 0;
13
+ const common_1 = require("./common");
14
+ const childLogger_1 = require("./childLogger");
15
+ class RabbitMqProducer {
16
+ constructor(logger, connectionFactory) {
17
+ this.logger = logger;
18
+ this.connectionFactory = connectionFactory;
19
+ this.logger = childLogger_1.createChildLogger(logger, "RabbitMqProducer");
20
+ }
21
+ publish(queue, message, options) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ const queueConfig = common_1.asQueueNameConfig(queue);
24
+ const settings = this.getQueueSettings(queueConfig.dlx);
25
+ const connection = yield this.connectionFactory.create();
26
+ const channel = yield connection.createChannel();
27
+ if (options === null || options === void 0 ? void 0 : options.prefetch) {
28
+ yield channel.prefetch(options.prefetch, options.globalPrefetch);
29
+ }
30
+ yield channel.assertQueue(queueConfig.name, settings);
31
+ if (!channel.sendToQueue(queueConfig.name, this.getMessageBuffer(message), {
32
+ persistent: true,
33
+ })) {
34
+ this.logger.error("unable to send message to queue '%j' {%j}", queueConfig, message);
35
+ throw new Error("Unable to send message");
36
+ }
37
+ this.logger.trace("message sent to queue '%s' (%j)", queueConfig.name, message);
38
+ return channel.close();
39
+ });
40
+ }
41
+ getMessageBuffer(message) {
42
+ return Buffer.from(JSON.stringify(message), "utf8");
43
+ }
44
+ getQueueSettings(deadletterExchangeName) {
45
+ return {
46
+ durable: true,
47
+ autoDelete: true,
48
+ arguments: {
49
+ "x-dead-letter-exchange": deadletterExchangeName,
50
+ },
51
+ };
52
+ }
53
+ }
54
+ exports.RabbitMqProducer = RabbitMqProducer;
@@ -0,0 +1,15 @@
1
+ /// <reference types="node" />
2
+ import * as amqp from "amqplib";
3
+ import { IRabbitMqConnectionFactory } from "./connectionFactory";
4
+ import { IQueueNameConfig } from "./common";
5
+ import { Logger } from "./childLogger";
6
+ export declare class RabbitMqPublisher {
7
+ private logger;
8
+ private connectionFactory;
9
+ constructor(logger: Logger, connectionFactory: IRabbitMqConnectionFactory);
10
+ publish<T>(queue: string | IQueueNameConfig, message: T, options?: IQueueNameConfig): Promise<void>;
11
+ private setupChannel;
12
+ protected getMessageBuffer<T>(message: T): Buffer;
13
+ protected getChannelSetup(channel: amqp.Channel, queueConfig: IQueueNameConfig): import("bluebird")<amqp.Replies.AssertExchange>[];
14
+ protected getSettings(): amqp.Options.AssertQueue;
15
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RabbitMqPublisher = void 0;
13
+ const common_1 = require("./common");
14
+ const childLogger_1 = require("./childLogger");
15
+ class RabbitMqPublisher {
16
+ constructor(logger, connectionFactory) {
17
+ this.logger = logger;
18
+ this.connectionFactory = connectionFactory;
19
+ this.logger = childLogger_1.createChildLogger(logger, "RabbitMqPublisher");
20
+ }
21
+ publish(queue, message, options) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ const queueConfig = common_1.asPubSubQueueNameConfig(queue);
24
+ try {
25
+ const connection = yield this.connectionFactory.create();
26
+ const channel = yield connection.createChannel();
27
+ if (options === null || options === void 0 ? void 0 : options.prefetch) {
28
+ channel.prefetch(options.prefetch, options.globalPrefetch);
29
+ }
30
+ yield this.setupChannel(channel, queueConfig);
31
+ channel.publish(queueConfig.dlx, "", this.getMessageBuffer(message));
32
+ this.logger.trace("message sent to exchange '%s' (%j)", queueConfig.dlx, message);
33
+ return channel.close();
34
+ }
35
+ catch (e) {
36
+ this.logger.error("unable to send message to exchange '%j' {%j}", queueConfig.dlx, message);
37
+ throw new Error("Unable to send message");
38
+ }
39
+ });
40
+ }
41
+ setupChannel(channel, queueConfig) {
42
+ this.logger.trace("setup '%j'", queueConfig);
43
+ return Promise.all(this.getChannelSetup(channel, queueConfig));
44
+ }
45
+ getMessageBuffer(message) {
46
+ return Buffer.from(JSON.stringify(message), "utf8");
47
+ }
48
+ getChannelSetup(channel, queueConfig) {
49
+ return [
50
+ channel.assertExchange(queueConfig.dlx, "fanout", this.getSettings()),
51
+ ];
52
+ }
53
+ getSettings() {
54
+ return {
55
+ durable: true,
56
+ autoDelete: true,
57
+ };
58
+ }
59
+ }
60
+ exports.RabbitMqPublisher = RabbitMqPublisher;
@@ -0,0 +1,19 @@
1
+ import * as amqp from "amqplib";
2
+ import { IRabbitMqConnectionFactory } from "./connectionFactory";
3
+ import { IQueueNameConfig } from "./common";
4
+ import { Logger } from "./childLogger";
5
+ export interface IRabbitMqSubscriberDisposer {
6
+ (): Promise<void>;
7
+ }
8
+ export declare class RabbitMqSubscriber {
9
+ private logger;
10
+ private connectionFactory;
11
+ constructor(logger: Logger, connectionFactory: IRabbitMqConnectionFactory);
12
+ subscribe<T>(queue: string | IQueueNameConfig, action: (message: T) => Promise<IRabbitMqSubscriberDisposer>, options?: Partial<IQueueNameConfig>): Promise<IRabbitMqSubscriberDisposer>;
13
+ private setupChannel;
14
+ private subscribeToChannel;
15
+ protected getMessageObject<T>(message: amqp.Message): T;
16
+ protected getChannelSetup(channel: amqp.Channel, queueConfig: IQueueNameConfig): Promise<string>;
17
+ protected getQueueSettings(): amqp.Options.AssertQueue;
18
+ protected getDLSettings(): amqp.Options.AssertQueue;
19
+ }
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RabbitMqSubscriber = void 0;
13
+ const common_1 = require("./common");
14
+ const childLogger_1 = require("./childLogger");
15
+ class RabbitMqSubscriber {
16
+ constructor(logger, connectionFactory) {
17
+ this.logger = logger;
18
+ this.connectionFactory = connectionFactory;
19
+ this.logger = childLogger_1.createChildLogger(logger, "RabbitMqConsumer");
20
+ }
21
+ subscribe(queue, action, options) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ const queueConfig = common_1.asPubSubQueueNameConfig(queue);
24
+ const connection = yield this.connectionFactory.create();
25
+ const channel = yield connection.createChannel();
26
+ if (options === null || options === void 0 ? void 0 : options.prefetch) {
27
+ yield channel.prefetch(options.prefetch, options.globalPrefetch);
28
+ }
29
+ this.logger.trace("got channel for queue '%s'", queueConfig.name);
30
+ const queueName = yield this.setupChannel(channel, Object.assign(Object.assign({}, queueConfig), options));
31
+ this.logger.debug("queue name generated for subscription queue '(%s)' is '(%s)'", queueConfig.name, queueName);
32
+ const queConfig = Object.assign(Object.assign({}, queueConfig), { dlq: queueName });
33
+ return this.subscribeToChannel(channel, queConfig, action);
34
+ });
35
+ }
36
+ setupChannel(channel, queueConfig) {
37
+ this.logger.trace("setup '%j'", queueConfig);
38
+ return this.getChannelSetup(channel, queueConfig);
39
+ }
40
+ subscribeToChannel(channel, queueConfig, action) {
41
+ return __awaiter(this, void 0, void 0, function* () {
42
+ this.logger.trace("subscribing to queue '%s'", queueConfig.name);
43
+ const opts = yield channel.consume(queueConfig.dlq, (message) => __awaiter(this, void 0, void 0, function* () {
44
+ let msg = this.getMessageObject(message);
45
+ this.logger.trace("message arrived from queue '%s' (%j)", queueConfig.name, msg);
46
+ try {
47
+ const disposer = yield action(msg);
48
+ this.logger.trace("message processed from queue '%s' (%j)", queueConfig.name, msg);
49
+ channel.ack(message);
50
+ return disposer;
51
+ }
52
+ catch (err) {
53
+ this.logger.error(err, "message processing failed from queue '%j' (%j)", queueConfig, msg);
54
+ channel.nack(message, false, false);
55
+ throw err;
56
+ }
57
+ }));
58
+ this.logger.trace("subscribed to queue '%s' (%s)", queueConfig.name, opts.consumerTag);
59
+ return (() => __awaiter(this, void 0, void 0, function* () {
60
+ this.logger.trace("disposing subscriber to queue '%s' (%s)", queueConfig.name, opts.consumerTag);
61
+ yield channel.close();
62
+ }));
63
+ });
64
+ }
65
+ getMessageObject(message) {
66
+ return JSON.parse(message.content.toString("utf8"));
67
+ }
68
+ getChannelSetup(channel, queueConfig) {
69
+ return __awaiter(this, void 0, void 0, function* () {
70
+ yield channel.assertExchange(queueConfig.dlx, "fanout", this.getDLSettings());
71
+ let result = yield channel.assertQueue(queueConfig.strictName ? queueConfig.name : queueConfig.dlq, this.getQueueSettings());
72
+ yield channel.bindQueue(result.queue, queueConfig.dlx, "");
73
+ return result.queue;
74
+ });
75
+ }
76
+ getQueueSettings() {
77
+ return {
78
+ exclusive: false,
79
+ autoDelete: true,
80
+ };
81
+ }
82
+ getDLSettings() {
83
+ return {
84
+ durable: true,
85
+ autoDelete: true,
86
+ };
87
+ }
88
+ }
89
+ exports.RabbitMqSubscriber = RabbitMqSubscriber;
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@rxdi/rabbitmq-pubsub",
3
+ "version": "0.7.118",
4
+ "description": "A graphql-subscriptions PubSub Engine using RabbitMQ",
5
+ "main": "dist/index.js",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/rxdi/graphql-rabbitmq-subscriptions.git"
9
+ },
10
+ "keywords": [
11
+ "graphql",
12
+ "rabbitmq",
13
+ "apollo",
14
+ "subscriptions"
15
+ ],
16
+ "license": "MIT",
17
+ "bugs": {
18
+ "url": "https://github.com/rxdi/graphql-rabbitmq-subscriptions/issues"
19
+ },
20
+ "homepage": "https://github.com/rxdi/graphql-rabbitmq-subscriptions",
21
+ "scripts": {
22
+ "test": "echo Test rabbitmq subscriptions",
23
+ "build": "tsc || true",
24
+ "lint": "tslint ./src/**/*.ts"
25
+ },
26
+ "dependencies": {
27
+ "amqplib": "^0.6.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/amqplib": "^0.5.17",
31
+ "@types/node": "^12.0.10",
32
+ "tslint": "^5.20.1",
33
+ "typescript": "^3.9.3"
34
+ },
35
+ "typings": "dist/index.d.ts",
36
+ "typescript": {
37
+ "definition": "dist/index.d.ts"
38
+ }
39
+ }