@opra/rabbitmq 1.12.2 → 1.12.4

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.
@@ -104,7 +104,16 @@ class RabbitmqAdapter extends core_1.PlatformAdapter {
104
104
  }
105
105
  /** Connect to server */
106
106
  for (const connectionOptions of this._config.connection) {
107
- const connection = await amqplib_1.default.connect(connectionOptions);
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
+ });
108
117
  this._connections.push(connection);
109
118
  const hostname = typeof connectionOptions === 'object'
110
119
  ? connectionOptions.hostname
@@ -127,8 +136,7 @@ class RabbitmqAdapter extends core_1.PlatformAdapter {
127
136
  return;
128
137
  await this.emitAsync('message', msg).catch(() => undefined);
129
138
  try {
130
- await args.handler(topic, msg);
131
- // channel.ack(msg);
139
+ await args.handler(channel, topic, msg);
132
140
  }
133
141
  catch (e) {
134
142
  this._emitError(e);
@@ -180,7 +188,7 @@ class RabbitmqAdapter extends core_1.PlatformAdapter {
180
188
  return;
181
189
  const operationConfig = {
182
190
  consumer: {
183
- noAck: true,
191
+ noAck: false,
184
192
  },
185
193
  };
186
194
  if (this._config.defaults) {
@@ -225,15 +233,28 @@ class RabbitmqAdapter extends core_1.PlatformAdapter {
225
233
  this[core_1.kAssetCache].set(header, 'decode', decode);
226
234
  }
227
235
  });
228
- args.handler = async (queue, message) => {
236
+ args.handler = async (channel, queue, message) => {
229
237
  if (!message)
230
238
  return;
231
239
  const operationHandler = instance[operation.name];
232
- let content;
233
240
  const headers = {};
241
+ /** Create context */
242
+ const context = new rabbitmq_context_js_1.RabbitmqContext({
243
+ adapter: this,
244
+ platform: this.platform,
245
+ controller,
246
+ controllerInstance: instance,
247
+ operation,
248
+ operationHandler,
249
+ queue,
250
+ channel,
251
+ message,
252
+ content: undefined,
253
+ headers,
254
+ });
234
255
  try {
235
256
  /** Parse and decode `payload` */
236
- content = await this._parseContent(message);
257
+ let content = await this._parseContent(message);
237
258
  if (content && decodePayload) {
238
259
  if (Buffer.isBuffer(content))
239
260
  content = content.toString('utf-8');
@@ -248,25 +269,12 @@ class RabbitmqAdapter extends core_1.PlatformAdapter {
248
269
  headers[k] = decode(Buffer.isBuffer(v) ? v.toString() : v);
249
270
  }
250
271
  }
272
+ context.content = content;
251
273
  }
252
274
  catch (e) {
253
- this._emitError(e);
275
+ this._emitError(e, context);
254
276
  return;
255
277
  }
256
- /** Create context */
257
- const context = new rabbitmq_context_js_1.RabbitmqContext({
258
- adapter: this,
259
- platform: this.platform,
260
- controller,
261
- controllerInstance: instance,
262
- operation,
263
- operationHandler,
264
- queue,
265
- fields: message.fields,
266
- properties: message.properties,
267
- content,
268
- headers,
269
- });
270
278
  await this.emitAsync('before-execute', context);
271
279
  try {
272
280
  /** Call operation handler */
@@ -339,7 +347,7 @@ class RabbitmqAdapter extends core_1.PlatformAdapter {
339
347
  else
340
348
  logger?.error(error);
341
349
  if (this.listenerCount('error'))
342
- this.emit('error', error);
350
+ this.emit('error', error, context);
343
351
  })
344
352
  .catch(noOp);
345
353
  }
@@ -18,6 +18,7 @@ class RabbitmqContext extends core_1.ExecutionContext {
18
18
  documentNode: init.controller?.node,
19
19
  protocol: 'rpc',
20
20
  });
21
+ this._ackSent = false;
21
22
  this.adapter = init.adapter;
22
23
  this.platform = init.adapter.platform;
23
24
  this.protocol = 'rpc';
@@ -29,11 +30,29 @@ class RabbitmqContext extends core_1.ExecutionContext {
29
30
  this.operation = init.operation;
30
31
  if (init.operationHandler)
31
32
  this.operationHandler = init.operationHandler;
33
+ this.channel = init.channel;
32
34
  this.queue = init.queue;
33
- this.fields = init.fields;
34
- this.properties = init.properties;
35
+ this.message = init.message;
35
36
  this.headers = init.headers || {};
36
37
  this.content = init.content;
37
38
  }
39
+ get properties() {
40
+ return this.message.properties;
41
+ }
42
+ get fields() {
43
+ return this.message.fields;
44
+ }
45
+ ack() {
46
+ if (this._ackSent)
47
+ return;
48
+ this._ackSent = true;
49
+ this.channel.ack(this.message);
50
+ }
51
+ nack() {
52
+ if (this._ackSent)
53
+ return;
54
+ this._ackSent = true;
55
+ this.channel.nack(this.message);
56
+ }
38
57
  }
39
58
  exports.RabbitmqContext = RabbitmqContext;
@@ -100,7 +100,16 @@ export class RabbitmqAdapter extends PlatformAdapter {
100
100
  }
101
101
  /** Connect to server */
102
102
  for (const connectionOptions of this._config.connection) {
103
- const connection = await amqplib.connect(connectionOptions);
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
+ });
104
113
  this._connections.push(connection);
105
114
  const hostname = typeof connectionOptions === 'object'
106
115
  ? connectionOptions.hostname
@@ -123,8 +132,7 @@ export class RabbitmqAdapter extends PlatformAdapter {
123
132
  return;
124
133
  await this.emitAsync('message', msg).catch(() => undefined);
125
134
  try {
126
- await args.handler(topic, msg);
127
- // channel.ack(msg);
135
+ await args.handler(channel, topic, msg);
128
136
  }
129
137
  catch (e) {
130
138
  this._emitError(e);
@@ -176,7 +184,7 @@ export class RabbitmqAdapter extends PlatformAdapter {
176
184
  return;
177
185
  const operationConfig = {
178
186
  consumer: {
179
- noAck: true,
187
+ noAck: false,
180
188
  },
181
189
  };
182
190
  if (this._config.defaults) {
@@ -221,15 +229,28 @@ export class RabbitmqAdapter extends PlatformAdapter {
221
229
  this[kAssetCache].set(header, 'decode', decode);
222
230
  }
223
231
  });
224
- args.handler = async (queue, message) => {
232
+ args.handler = async (channel, queue, message) => {
225
233
  if (!message)
226
234
  return;
227
235
  const operationHandler = instance[operation.name];
228
- let content;
229
236
  const headers = {};
237
+ /** Create context */
238
+ const context = new RabbitmqContext({
239
+ adapter: this,
240
+ platform: this.platform,
241
+ controller,
242
+ controllerInstance: instance,
243
+ operation,
244
+ operationHandler,
245
+ queue,
246
+ channel,
247
+ message,
248
+ content: undefined,
249
+ headers,
250
+ });
230
251
  try {
231
252
  /** Parse and decode `payload` */
232
- content = await this._parseContent(message);
253
+ let content = await this._parseContent(message);
233
254
  if (content && decodePayload) {
234
255
  if (Buffer.isBuffer(content))
235
256
  content = content.toString('utf-8');
@@ -244,25 +265,12 @@ export class RabbitmqAdapter extends PlatformAdapter {
244
265
  headers[k] = decode(Buffer.isBuffer(v) ? v.toString() : v);
245
266
  }
246
267
  }
268
+ context.content = content;
247
269
  }
248
270
  catch (e) {
249
- this._emitError(e);
271
+ this._emitError(e, context);
250
272
  return;
251
273
  }
252
- /** Create context */
253
- const context = new RabbitmqContext({
254
- adapter: this,
255
- platform: this.platform,
256
- controller,
257
- controllerInstance: instance,
258
- operation,
259
- operationHandler,
260
- queue,
261
- fields: message.fields,
262
- properties: message.properties,
263
- content,
264
- headers,
265
- });
266
274
  await this.emitAsync('before-execute', context);
267
275
  try {
268
276
  /** Call operation handler */
@@ -335,7 +343,7 @@ export class RabbitmqAdapter extends PlatformAdapter {
335
343
  else
336
344
  logger?.error(error);
337
345
  if (this.listenerCount('error'))
338
- this.emit('error', error);
346
+ this.emit('error', error, context);
339
347
  })
340
348
  .catch(noOp);
341
349
  }
@@ -15,6 +15,7 @@ export class RabbitmqContext extends ExecutionContext {
15
15
  documentNode: init.controller?.node,
16
16
  protocol: 'rpc',
17
17
  });
18
+ this._ackSent = false;
18
19
  this.adapter = init.adapter;
19
20
  this.platform = init.adapter.platform;
20
21
  this.protocol = 'rpc';
@@ -26,10 +27,28 @@ export class RabbitmqContext extends ExecutionContext {
26
27
  this.operation = init.operation;
27
28
  if (init.operationHandler)
28
29
  this.operationHandler = init.operationHandler;
30
+ this.channel = init.channel;
29
31
  this.queue = init.queue;
30
- this.fields = init.fields;
31
- this.properties = init.properties;
32
+ this.message = init.message;
32
33
  this.headers = init.headers || {};
33
34
  this.content = init.content;
34
35
  }
36
+ get properties() {
37
+ return this.message.properties;
38
+ }
39
+ get fields() {
40
+ return this.message.fields;
41
+ }
42
+ ack() {
43
+ if (this._ackSent)
44
+ return;
45
+ this._ackSent = true;
46
+ this.channel.ack(this.message);
47
+ }
48
+ nack() {
49
+ if (this._ackSent)
50
+ return;
51
+ this._ackSent = true;
52
+ this.channel.nack(this.message);
53
+ }
35
54
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opra/rabbitmq",
3
- "version": "1.12.2",
3
+ "version": "1.12.4",
4
4
  "description": "Opra RabbitMQ package",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
@@ -10,11 +10,11 @@
10
10
  "iconv-lite": "^0.6.3",
11
11
  "node-events-async": "^1.0.0",
12
12
  "tslib": "^2.8.1",
13
- "valgen": "^5.13.0"
13
+ "valgen": "^5.13.3"
14
14
  },
15
15
  "peerDependencies": {
16
- "@opra/common": "^1.12.2",
17
- "@opra/core": "^1.12.2",
16
+ "@opra/common": "^1.12.4",
17
+ "@opra/core": "^1.12.4",
18
18
  "amqplib": "^0.10.5"
19
19
  },
20
20
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  import { ApiDocument, OpraException, OpraSchema, RpcApi, RpcController, RpcOperation } from '@opra/common';
2
2
  import { PlatformAdapter } from '@opra/core';
3
- import amqplib from 'amqplib';
3
+ import amqplib, { Channel } from 'amqplib';
4
4
  import { ConsumeMessage } from 'amqplib/properties';
5
5
  import { RabbitmqContext } from './rabbitmq-context.js';
6
6
  export interface OperationConfig {
@@ -12,7 +12,7 @@ interface HandlerArguments {
12
12
  instance: any;
13
13
  operation: RpcOperation;
14
14
  operationConfig: OperationConfig;
15
- handler: (queue: string, msg: ConsumeMessage | null) => void | Promise<void>;
15
+ handler: (channel: Channel, queue: string, msg: ConsumeMessage | null) => void | Promise<void>;
16
16
  topics: string[];
17
17
  }
18
18
  /**
@@ -1,6 +1,7 @@
1
1
  import { OpraSchema, RpcController, RpcOperation } from '@opra/common';
2
2
  import { ExecutionContext } from '@opra/core';
3
- import amqplib from 'amqplib';
3
+ import type { Channel } from 'amqplib';
4
+ import type { ConsumeMessage } from 'amqplib/properties';
4
5
  import type { AsyncEventEmitter } from 'node-events-async';
5
6
  import type { RabbitmqAdapter } from './rabbitmq-adapter';
6
7
  /**
@@ -8,6 +9,7 @@ import type { RabbitmqAdapter } from './rabbitmq-adapter';
8
9
  * It extends the ExecutionContext and implements the AsyncEventEmitter.
9
10
  */
10
11
  export declare class RabbitmqContext extends ExecutionContext implements AsyncEventEmitter {
12
+ private _ackSent;
11
13
  readonly protocol: OpraSchema.Transport;
12
14
  readonly platform: string;
13
15
  readonly adapter: RabbitmqAdapter;
@@ -16,8 +18,8 @@ export declare class RabbitmqContext extends ExecutionContext implements AsyncEv
16
18
  readonly operation?: RpcOperation;
17
19
  readonly operationHandler?: Function;
18
20
  readonly queue: string;
19
- readonly fields: amqplib.MessageFields;
20
- readonly properties: amqplib.MessageProperties;
21
+ readonly channel: Channel;
22
+ readonly message: ConsumeMessage;
21
23
  readonly content: any;
22
24
  readonly headers: Record<string, any>;
23
25
  /**
@@ -25,10 +27,15 @@ export declare class RabbitmqContext extends ExecutionContext implements AsyncEv
25
27
  * @param init the context options
26
28
  */
27
29
  constructor(init: RabbitmqContext.Initiator);
30
+ get properties(): import("amqplib").MessageProperties;
31
+ get fields(): import("amqplib").ConsumeMessageFields;
32
+ ack(): void;
33
+ nack(): void;
28
34
  }
29
35
  export declare namespace RabbitmqContext {
30
36
  interface Initiator extends Omit<ExecutionContext.Initiator, 'document' | 'protocol' | 'documentNode'> {
31
37
  adapter: RabbitmqAdapter;
38
+ channel: Channel;
32
39
  controller?: RpcController;
33
40
  controllerInstance?: any;
34
41
  operation?: RpcOperation;
@@ -36,7 +43,6 @@ export declare namespace RabbitmqContext {
36
43
  content: any;
37
44
  headers: Record<string, any>;
38
45
  queue: string;
39
- fields: amqplib.MessageFields;
40
- properties: amqplib.MessageProperties;
46
+ message: ConsumeMessage;
41
47
  }
42
48
  }