@opra/rabbitmq 1.15.1 → 1.16.0

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.
@@ -6,7 +6,7 @@ const node_zlib_1 = tslib_1.__importDefault(require("node:zlib"));
6
6
  const type_is_1 = tslib_1.__importDefault(require("@browsery/type-is"));
7
7
  const common_1 = require("@opra/common");
8
8
  const core_1 = require("@opra/core");
9
- const amqplib_1 = tslib_1.__importDefault(require("amqplib"));
9
+ const amqp_connection_manager_1 = require("amqp-connection-manager");
10
10
  const content_type_1 = require("content-type");
11
11
  const iconv_lite_1 = tslib_1.__importDefault(require("iconv-lite"));
12
12
  const util_1 = require("util");
@@ -34,7 +34,6 @@ class RabbitmqAdapter extends core_1.PlatformAdapter {
34
34
  constructor(document, config) {
35
35
  super(config);
36
36
  this._controllerInstances = new Map();
37
- this._connections = [];
38
37
  this._status = 'idle';
39
38
  this.protocol = 'rpc';
40
39
  this.platform = RabbitmqAdapter.PlatformName;
@@ -102,54 +101,54 @@ class RabbitmqAdapter extends core_1.PlatformAdapter {
102
101
  handlerArgs.push(args);
103
102
  }
104
103
  }
105
- /** Connect to server */
106
- for (const connectionOptions of this._config.connection) {
107
- const connection = await amqplib_1.default.connect(connectionOptions).catch(e => {
108
- e.message = 'Unable to connect to RabbitMQ server';
109
- throw new Error('Unable to connect to RabbitMQ server (' +
110
- (typeof connectionOptions == 'object'
111
- ? connectionOptions.hostname + ':' + connectionOptions.port
112
- : connectionOptions) +
113
- ')',
114
- // @ts-ignore
115
- e);
116
- });
117
- this._connections.push(connection);
118
- const hostname = typeof connectionOptions === 'object'
119
- ? connectionOptions.hostname
120
- : connectionOptions;
121
- this.logger?.info?.(`Connected to ${hostname}`);
122
- /** Subscribe to channels */
123
- for (const args of handlerArgs) {
124
- /** Create channel per operation */
125
- const channel = await connection.createChannel();
126
- for (const topic of args.topics) {
127
- const opts = this._config.queues?.[topic];
128
- if (opts)
129
- await channel.assertQueue(topic, opts);
104
+ const connectionOptions = typeof this._config.connection === 'string'
105
+ ? {
106
+ urls: [this._config.connection],
107
+ }
108
+ : Array.isArray(this._config.connection)
109
+ ? {
110
+ urls: this._config.connection,
130
111
  }
131
- for (const topic of args.topics) {
132
- await channel.assertQueue(topic);
133
- await channel
134
- .consume(topic, async (msg) => {
135
- if (!msg)
136
- return;
137
- await this.emitAsync('message', msg, topic).catch(noOp);
138
- try {
139
- await args.handler(channel, topic, msg);
140
- }
141
- catch (e) {
142
- this._emitError(e);
143
- }
144
- },
145
- /** Consume options */
146
- args.operationConfig.consumer)
147
- .catch(e => {
112
+ : this._config.connection;
113
+ this._client = new amqp_connection_manager_1.AmqpConnectionManagerClass(connectionOptions.urls, connectionOptions);
114
+ this._client.connect().catch(e => {
115
+ e.message =
116
+ 'Unable to connect to RabbitMQ server at ' +
117
+ connectionOptions.urls +
118
+ '. ' +
119
+ e.message;
120
+ throw e;
121
+ });
122
+ this.logger?.info?.(`Connected RabbitMQ at ${connectionOptions.urls}`);
123
+ for (const args of handlerArgs) {
124
+ /** Create channel per operation */
125
+ const channel = this._client.createChannel();
126
+ for (const topic of args.topics) {
127
+ const opts = this._config.queues?.[topic];
128
+ if (opts)
129
+ await channel.assertQueue(topic, opts);
130
+ }
131
+ for (const topic of args.topics) {
132
+ await channel.assertQueue(topic);
133
+ await channel
134
+ .consume(topic, async (msg) => {
135
+ if (!msg)
136
+ return;
137
+ await this.emitAsync('message', msg, topic).catch(noOp);
138
+ try {
139
+ await args.handler(channel, topic, msg);
140
+ }
141
+ catch (e) {
148
142
  this._emitError(e);
149
- throw e;
150
- });
151
- this.logger?.info?.(`Subscribed to topic${args.topics.length > 1 ? 's' : ''} "${args.topics}"`);
152
- }
143
+ }
144
+ },
145
+ /** Consume options */
146
+ args.operationConfig.consumer)
147
+ .catch(e => {
148
+ this._emitError(e);
149
+ throw e;
150
+ });
151
+ this.logger?.info?.(`Subscribed to topic${args.topics.length > 1 ? 's' : ''} "${args.topics}"`);
153
152
  }
154
153
  }
155
154
  this._status = 'started';
@@ -163,8 +162,8 @@ class RabbitmqAdapter extends core_1.PlatformAdapter {
163
162
  * Closes all connections and stops the service
164
163
  */
165
164
  async close() {
166
- await Promise.all(this._connections.map(c => c.close()));
167
- this._connections = [];
165
+ await this._client?.close();
166
+ this._client = undefined;
168
167
  this._controllerInstances.clear();
169
168
  this._status = 'idle';
170
169
  }
@@ -187,7 +186,7 @@ class RabbitmqAdapter extends core_1.PlatformAdapter {
187
186
  return;
188
187
  const operationConfig = {
189
188
  consumer: {
190
- noAck: false,
189
+ noAck: true,
191
190
  },
192
191
  };
193
192
  if (this._config.defaults) {
@@ -2,7 +2,7 @@ import zlib from 'node:zlib';
2
2
  import typeIs from '@browsery/type-is';
3
3
  import { OpraException, RPC_CONTROLLER_METADATA, RpcApi, } from '@opra/common';
4
4
  import { kAssetCache, PlatformAdapter } from '@opra/core';
5
- import amqplib from 'amqplib';
5
+ import { AmqpConnectionManagerClass, } from 'amqp-connection-manager';
6
6
  import { parse as parseContentType } from 'content-type';
7
7
  import iconv from 'iconv-lite';
8
8
  import { promisify } from 'util';
@@ -30,7 +30,6 @@ export class RabbitmqAdapter extends PlatformAdapter {
30
30
  constructor(document, config) {
31
31
  super(config);
32
32
  this._controllerInstances = new Map();
33
- this._connections = [];
34
33
  this._status = 'idle';
35
34
  this.protocol = 'rpc';
36
35
  this.platform = RabbitmqAdapter.PlatformName;
@@ -98,54 +97,54 @@ export class RabbitmqAdapter extends PlatformAdapter {
98
97
  handlerArgs.push(args);
99
98
  }
100
99
  }
101
- /** Connect to server */
102
- for (const connectionOptions of this._config.connection) {
103
- const connection = await amqplib.connect(connectionOptions).catch(e => {
104
- e.message = 'Unable to connect to RabbitMQ server';
105
- throw new Error('Unable to connect to RabbitMQ server (' +
106
- (typeof connectionOptions == 'object'
107
- ? connectionOptions.hostname + ':' + connectionOptions.port
108
- : connectionOptions) +
109
- ')',
110
- // @ts-ignore
111
- e);
112
- });
113
- this._connections.push(connection);
114
- const hostname = typeof connectionOptions === 'object'
115
- ? connectionOptions.hostname
116
- : connectionOptions;
117
- this.logger?.info?.(`Connected to ${hostname}`);
118
- /** Subscribe to channels */
119
- for (const args of handlerArgs) {
120
- /** Create channel per operation */
121
- const channel = await connection.createChannel();
122
- for (const topic of args.topics) {
123
- const opts = this._config.queues?.[topic];
124
- if (opts)
125
- await channel.assertQueue(topic, opts);
100
+ const connectionOptions = typeof this._config.connection === 'string'
101
+ ? {
102
+ urls: [this._config.connection],
103
+ }
104
+ : Array.isArray(this._config.connection)
105
+ ? {
106
+ urls: this._config.connection,
126
107
  }
127
- for (const topic of args.topics) {
128
- await channel.assertQueue(topic);
129
- await channel
130
- .consume(topic, async (msg) => {
131
- if (!msg)
132
- return;
133
- await this.emitAsync('message', msg, topic).catch(noOp);
134
- try {
135
- await args.handler(channel, topic, msg);
136
- }
137
- catch (e) {
138
- this._emitError(e);
139
- }
140
- },
141
- /** Consume options */
142
- args.operationConfig.consumer)
143
- .catch(e => {
108
+ : this._config.connection;
109
+ this._client = new AmqpConnectionManagerClass(connectionOptions.urls, connectionOptions);
110
+ this._client.connect().catch(e => {
111
+ e.message =
112
+ 'Unable to connect to RabbitMQ server at ' +
113
+ connectionOptions.urls +
114
+ '. ' +
115
+ e.message;
116
+ throw e;
117
+ });
118
+ this.logger?.info?.(`Connected RabbitMQ at ${connectionOptions.urls}`);
119
+ for (const args of handlerArgs) {
120
+ /** Create channel per operation */
121
+ const channel = this._client.createChannel();
122
+ for (const topic of args.topics) {
123
+ const opts = this._config.queues?.[topic];
124
+ if (opts)
125
+ await channel.assertQueue(topic, opts);
126
+ }
127
+ for (const topic of args.topics) {
128
+ await channel.assertQueue(topic);
129
+ await channel
130
+ .consume(topic, async (msg) => {
131
+ if (!msg)
132
+ return;
133
+ await this.emitAsync('message', msg, topic).catch(noOp);
134
+ try {
135
+ await args.handler(channel, topic, msg);
136
+ }
137
+ catch (e) {
144
138
  this._emitError(e);
145
- throw e;
146
- });
147
- this.logger?.info?.(`Subscribed to topic${args.topics.length > 1 ? 's' : ''} "${args.topics}"`);
148
- }
139
+ }
140
+ },
141
+ /** Consume options */
142
+ args.operationConfig.consumer)
143
+ .catch(e => {
144
+ this._emitError(e);
145
+ throw e;
146
+ });
147
+ this.logger?.info?.(`Subscribed to topic${args.topics.length > 1 ? 's' : ''} "${args.topics}"`);
149
148
  }
150
149
  }
151
150
  this._status = 'started';
@@ -159,8 +158,8 @@ export class RabbitmqAdapter extends PlatformAdapter {
159
158
  * Closes all connections and stops the service
160
159
  */
161
160
  async close() {
162
- await Promise.all(this._connections.map(c => c.close()));
163
- this._connections = [];
161
+ await this._client?.close();
162
+ this._client = undefined;
164
163
  this._controllerInstances.clear();
165
164
  this._status = 'idle';
166
165
  }
@@ -183,7 +182,7 @@ export class RabbitmqAdapter extends PlatformAdapter {
183
182
  return;
184
183
  const operationConfig = {
185
184
  consumer: {
186
- noAck: false,
185
+ noAck: true,
187
186
  },
188
187
  };
189
188
  if (this._config.defaults) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opra/rabbitmq",
3
- "version": "1.15.1",
3
+ "version": "1.16.0",
4
4
  "description": "Opra RabbitMQ package",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
@@ -13,8 +13,9 @@
13
13
  "valgen": "^5.15.0"
14
14
  },
15
15
  "peerDependencies": {
16
- "@opra/common": "^1.15.1",
17
- "@opra/core": "^1.15.1",
16
+ "@opra/common": "^1.16.0",
17
+ "@opra/core": "^1.16.0",
18
+ "amqp-connection-manager": "^4.1.14",
18
19
  "amqplib": "^0.10.7"
19
20
  },
20
21
  "type": "module",
@@ -1,6 +1,7 @@
1
1
  import { ApiDocument, OpraException, OpraSchema, RpcApi, RpcController, RpcOperation } from '@opra/common';
2
2
  import { PlatformAdapter } from '@opra/core';
3
- import amqplib, { Channel } from 'amqplib';
3
+ import { type AmqpConnectionManager, type AmqpConnectionManagerOptions, type ChannelWrapper, type ConnectionUrl } from 'amqp-connection-manager';
4
+ import amqplib from 'amqplib';
4
5
  import { ConsumeMessage } from 'amqplib/properties';
5
6
  import { RabbitmqContext } from './rabbitmq-context.js';
6
7
  export interface OperationConfig {
@@ -12,7 +13,7 @@ interface HandlerArguments {
12
13
  instance: any;
13
14
  operation: RpcOperation;
14
15
  operationConfig: OperationConfig;
15
- handler: (channel: Channel, queue: string, msg: ConsumeMessage | null) => void | Promise<void>;
16
+ handler: (channel: ChannelWrapper, queue: string, msg: ConsumeMessage | null) => void | Promise<void>;
16
17
  topics: string[];
17
18
  }
18
19
  /**
@@ -23,7 +24,7 @@ export declare class RabbitmqAdapter extends PlatformAdapter<RabbitmqAdapter.Eve
23
24
  static readonly PlatformName = "rabbitmq";
24
25
  protected _config: RabbitmqAdapter.Config;
25
26
  protected _controllerInstances: Map<RpcController, any>;
26
- protected _connections: amqplib.ChannelModel[];
27
+ protected _client?: AmqpConnectionManager;
27
28
  protected _status: RabbitmqAdapter.Status;
28
29
  readonly protocol: OpraSchema.Transport;
29
30
  readonly platform = "rabbitmq";
@@ -71,9 +72,11 @@ export declare class RabbitmqAdapter extends PlatformAdapter<RabbitmqAdapter.Eve
71
72
  export declare namespace RabbitmqAdapter {
72
73
  type NextCallback = () => Promise<any>;
73
74
  type Status = 'idle' | 'starting' | 'started';
74
- type ConnectionOptions = amqplib.Options.Connect;
75
+ interface ConnectionOptions extends AmqpConnectionManagerOptions {
76
+ urls?: ConnectionUrl[];
77
+ }
75
78
  interface Config extends PlatformAdapter.Options {
76
- connection: (string | ConnectionOptions)[];
79
+ connection: string | string[] | ConnectionOptions;
77
80
  queues?: Record<string, amqplib.Options.AssertQueue>;
78
81
  defaults?: {
79
82
  consumer?: amqplib.Options.Consume;
@@ -1,6 +1,6 @@
1
1
  import { OpraSchema, RpcController, RpcOperation } from '@opra/common';
2
2
  import { ExecutionContext } from '@opra/core';
3
- import type { Channel } from 'amqplib';
3
+ import type { ChannelWrapper } from 'amqp-connection-manager';
4
4
  import type { ConsumeMessage } from 'amqplib/properties';
5
5
  import type { AsyncEventEmitter } from 'node-events-async';
6
6
  import type { RabbitmqAdapter } from './rabbitmq-adapter';
@@ -18,7 +18,7 @@ export declare class RabbitmqContext extends ExecutionContext implements AsyncEv
18
18
  readonly operation?: RpcOperation;
19
19
  readonly operationHandler?: Function;
20
20
  readonly queue: string;
21
- readonly channel: Channel;
21
+ readonly channel: ChannelWrapper;
22
22
  readonly message: ConsumeMessage;
23
23
  readonly content: any;
24
24
  readonly headers: Record<string, any>;
@@ -27,15 +27,15 @@ export declare class RabbitmqContext extends ExecutionContext implements AsyncEv
27
27
  * @param init the context options
28
28
  */
29
29
  constructor(init: RabbitmqContext.Initiator);
30
- get properties(): import("amqplib").MessageProperties;
31
- get fields(): import("amqplib").ConsumeMessageFields;
30
+ get properties(): import("amqplib/properties").MessageProperties;
31
+ get fields(): import("amqplib/properties").ConsumeMessageFields;
32
32
  ack(): void;
33
33
  nack(): void;
34
34
  }
35
35
  export declare namespace RabbitmqContext {
36
36
  interface Initiator extends Omit<ExecutionContext.Initiator, 'document' | 'protocol' | 'documentNode'> {
37
37
  adapter: RabbitmqAdapter;
38
- channel: Channel;
38
+ channel: ChannelWrapper;
39
39
  controller?: RpcController;
40
40
  controllerInstance?: any;
41
41
  operation?: RpcOperation;