@onify/fake-amqplib 2.0.0 → 3.1.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.
- package/README.md +10 -10
- package/index.d.ts +8 -12
- package/index.js +309 -117
- package/main.cjs +309 -117
- package/package.json +9 -7
package/main.cjs
CHANGED
|
@@ -6,8 +6,26 @@ var url = require('url');
|
|
|
6
6
|
|
|
7
7
|
const kSmqp = Symbol.for('smqp');
|
|
8
8
|
const kClosed = Symbol.for('closed');
|
|
9
|
-
const
|
|
9
|
+
const kDeliveryTag = Symbol.for('channel delivery tag');
|
|
10
10
|
const kPrefetch = Symbol.for('prefetch');
|
|
11
|
+
const kChannelPrefetch = Symbol.for('channel prefetch');
|
|
12
|
+
|
|
13
|
+
class AmqplibBroker extends smqp.Broker {
|
|
14
|
+
constructor(...args) {
|
|
15
|
+
super(...args);
|
|
16
|
+
this[kDeliveryTag] = 0;
|
|
17
|
+
}
|
|
18
|
+
_getNextDeliveryTag() {
|
|
19
|
+
return ++this[kDeliveryTag];
|
|
20
|
+
}
|
|
21
|
+
_getMessageByDeliveryTag(queue, deliveryTag) {
|
|
22
|
+
const q = this.getQueue(queue);
|
|
23
|
+
return q.messages.find((m) => m.fields.deliveryTag === deliveryTag);
|
|
24
|
+
}
|
|
25
|
+
_getChannelConsumers(channelName) {
|
|
26
|
+
return this.getConsumers().filter((f) => f.options.channelName === channelName);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
11
29
|
|
|
12
30
|
class FakeAmqpError extends Error {
|
|
13
31
|
constructor(message, code, killChannel, killConnection) {
|
|
@@ -20,27 +38,55 @@ class FakeAmqpError extends Error {
|
|
|
20
38
|
|
|
21
39
|
class FakeAmqpNotFoundError extends FakeAmqpError {
|
|
22
40
|
constructor(type, name, vhost, killConnection = false) {
|
|
23
|
-
super(
|
|
41
|
+
super(
|
|
42
|
+
`Channel closed by server: 404 (NOT-FOUND) with message "NOT_FOUND - no ${type} '${name}' in vhost '${vhost || '/'}'`,
|
|
43
|
+
404,
|
|
44
|
+
true,
|
|
45
|
+
killConnection,
|
|
46
|
+
);
|
|
24
47
|
}
|
|
25
48
|
}
|
|
26
49
|
|
|
27
|
-
class
|
|
50
|
+
class FakeAmqpUnknownDeliveryTag extends FakeAmqpError {
|
|
51
|
+
constructor(deliveryTag) {
|
|
52
|
+
super(
|
|
53
|
+
`Channel closed by server: 406 (PRECONDITION-FAILED) with message "PRECONDITION_FAILED - unknown delivery tag ${deliveryTag}`,
|
|
54
|
+
406,
|
|
55
|
+
true,
|
|
56
|
+
false,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
get _emit() {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function Message(smqpMessage, deliveryTag) {
|
|
65
|
+
this[kSmqp] = smqpMessage;
|
|
66
|
+
this.fields = { ...smqpMessage.fields, deliveryTag };
|
|
67
|
+
this.content = Buffer.from(smqpMessage.content);
|
|
68
|
+
this.properties = { ...smqpMessage.properties };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
class FakeAmqplibChannel extends events.EventEmitter {
|
|
28
72
|
constructor(broker, connection) {
|
|
73
|
+
super();
|
|
29
74
|
this.connection = connection;
|
|
30
75
|
|
|
31
76
|
this[kPrefetch] = 10000;
|
|
77
|
+
this[kChannelPrefetch] = Infinity;
|
|
32
78
|
this[kClosed] = false;
|
|
33
|
-
this
|
|
34
|
-
this._channelName = `channel-${generateId()}`;
|
|
79
|
+
const channelName = (this._channelName = `channel-${generateId()}`);
|
|
35
80
|
this._version = connection._version;
|
|
36
81
|
this._broker = broker;
|
|
37
82
|
|
|
83
|
+
this._channelQueue = broker.assertQueue(`#${channelName}`);
|
|
38
84
|
this._emitReturn = this._emitReturn.bind(this);
|
|
39
85
|
|
|
40
86
|
broker.on('return', this._emitReturn);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
87
|
+
|
|
88
|
+
this._createChannelMessage = this._createChannelMessage.bind(this);
|
|
89
|
+
this._calculateChannelCapacity = this._calculateChannelCapacity.bind(this);
|
|
44
90
|
}
|
|
45
91
|
get _closed() {
|
|
46
92
|
return this[kClosed];
|
|
@@ -70,12 +116,12 @@ class FakeAmqplibChannel {
|
|
|
70
116
|
}
|
|
71
117
|
bindExchange(destination, source, ...args) {
|
|
72
118
|
const broker = this._broker;
|
|
73
|
-
return Promise.all([
|
|
119
|
+
return Promise.all([this.checkExchange(source), this.checkExchange(destination)]).then(() => {
|
|
74
120
|
return this._callBroker(broker.bindExchange, source, destination, ...args);
|
|
75
121
|
});
|
|
76
122
|
}
|
|
77
123
|
bindQueue(queue, source, ...args) {
|
|
78
|
-
return Promise.all([
|
|
124
|
+
return Promise.all([this.checkQueue(queue), this.checkExchange(source)]).then(() => {
|
|
79
125
|
return this._callBroker(this._broker.bindQueue, queue, source, ...args);
|
|
80
126
|
});
|
|
81
127
|
}
|
|
@@ -106,14 +152,16 @@ class FakeAmqplibChannel {
|
|
|
106
152
|
}
|
|
107
153
|
get(queue, ...args) {
|
|
108
154
|
const connPath = this.connection._url.pathname;
|
|
155
|
+
const createMessage = this._createChannelMessage;
|
|
109
156
|
return this._callBroker(getMessage, ...args);
|
|
110
157
|
|
|
111
158
|
function getMessage(...getargs) {
|
|
112
159
|
const q = this.getQueue(queue);
|
|
113
|
-
if (!q) throw new FakeAmqpNotFoundError('queue', queue, connPath
|
|
160
|
+
if (!q) throw new FakeAmqpNotFoundError('queue', queue, connPath);
|
|
114
161
|
const msg = q.get(...getargs) || false;
|
|
115
162
|
if (!msg) return msg;
|
|
116
|
-
|
|
163
|
+
|
|
164
|
+
return createMessage(msg, args[0]?.noAck);
|
|
117
165
|
}
|
|
118
166
|
}
|
|
119
167
|
deleteExchange(exchange, ...args) {
|
|
@@ -140,15 +188,17 @@ class FakeAmqplibChannel {
|
|
|
140
188
|
if (!Buffer.isBuffer(content)) throw new TypeError('content is not a buffer');
|
|
141
189
|
if (exchange === '') return this.sendToQueue(routingKey, content, options, callback);
|
|
142
190
|
|
|
143
|
-
const args = [
|
|
191
|
+
const args = [this._broker.publish, exchange, routingKey, content];
|
|
144
192
|
|
|
145
193
|
args.push(options, callback);
|
|
146
194
|
|
|
147
|
-
this.checkExchange(exchange)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
195
|
+
this.checkExchange(exchange)
|
|
196
|
+
.then(() => {
|
|
197
|
+
return this._callBroker(...args);
|
|
198
|
+
})
|
|
199
|
+
.catch((err) => {
|
|
200
|
+
this.emit('error', err);
|
|
201
|
+
});
|
|
152
202
|
|
|
153
203
|
return true;
|
|
154
204
|
}
|
|
@@ -165,15 +215,17 @@ class FakeAmqplibChannel {
|
|
|
165
215
|
sendToQueue(queue, content, options, callback) {
|
|
166
216
|
if (!Buffer.isBuffer(content)) throw new TypeError('content is not a buffer');
|
|
167
217
|
|
|
168
|
-
const args = [
|
|
218
|
+
const args = [this._broker.sendToQueue, queue, content];
|
|
169
219
|
|
|
170
220
|
args.push(options, callback);
|
|
171
221
|
|
|
172
|
-
this.checkQueue(queue)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
222
|
+
this.checkQueue(queue)
|
|
223
|
+
.then(() => {
|
|
224
|
+
return this._callBroker(...args);
|
|
225
|
+
})
|
|
226
|
+
.catch((err) => {
|
|
227
|
+
this.emit('error', err);
|
|
228
|
+
});
|
|
177
229
|
|
|
178
230
|
return true;
|
|
179
231
|
}
|
|
@@ -216,31 +268,47 @@ class FakeAmqplibChannel {
|
|
|
216
268
|
}
|
|
217
269
|
consume(queue, onMessage, options = {}, callback) {
|
|
218
270
|
const { _id: connId, _url: connUrl } = this.connection;
|
|
271
|
+
const createMessage = this._createChannelMessage;
|
|
272
|
+
const calculateCapacity = this._calculateChannelCapacity;
|
|
219
273
|
const channelName = this._channelName;
|
|
220
274
|
const prefetch = this[kPrefetch];
|
|
221
275
|
|
|
222
|
-
return this._callBroker(
|
|
276
|
+
return this._callBroker(consume, callback);
|
|
223
277
|
|
|
224
|
-
function
|
|
278
|
+
function consume() {
|
|
225
279
|
const q = queue && this.getQueue(queue);
|
|
226
280
|
if (!q) {
|
|
227
281
|
throw new FakeAmqpNotFoundError('queue', queue, connUrl.pathname);
|
|
228
282
|
}
|
|
229
283
|
|
|
230
284
|
if (q.exclusive || (q.options.exclusive && q.options._connectionId !== connId)) {
|
|
231
|
-
throw new FakeAmqpError(
|
|
285
|
+
throw new FakeAmqpError(
|
|
286
|
+
`Channel closed by server: 403 (ACCESS-REFUSED) with message "ACCESS_REFUSED - queue '${queue}' in vhost '${connUrl.pathname}' in exclusive use"`,
|
|
287
|
+
403,
|
|
288
|
+
true,
|
|
289
|
+
true,
|
|
290
|
+
);
|
|
232
291
|
}
|
|
233
292
|
|
|
234
|
-
const
|
|
293
|
+
const consumer = this.consume(queue, onMessage && handler, {
|
|
235
294
|
...options,
|
|
236
295
|
channelName,
|
|
237
|
-
prefetch,
|
|
296
|
+
prefetch: calculateCapacity(prefetch),
|
|
297
|
+
_consumerPrefetch: prefetch,
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
const capacityProp = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(consumer), 'capacity');
|
|
301
|
+
Object.defineProperty(consumer, 'capacity', {
|
|
302
|
+
get() {
|
|
303
|
+
return calculateCapacity(capacityProp.get.call(this));
|
|
304
|
+
},
|
|
238
305
|
});
|
|
239
|
-
|
|
306
|
+
|
|
307
|
+
return { consumerTag: consumer.consumerTag };
|
|
240
308
|
}
|
|
241
309
|
|
|
242
310
|
function handler(_, msg) {
|
|
243
|
-
onMessage(
|
|
311
|
+
onMessage(createMessage(msg, options.noAck));
|
|
244
312
|
}
|
|
245
313
|
}
|
|
246
314
|
cancel(consumerTag, ...args) {
|
|
@@ -248,51 +316,137 @@ class FakeAmqplibChannel {
|
|
|
248
316
|
}
|
|
249
317
|
close(callback) {
|
|
250
318
|
if (this[kClosed]) return;
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
broker.off('return', this._emitReturn);
|
|
255
|
-
const channelConsumers = broker.getConsumers().filter((f) => f.options.channelName === channelName);
|
|
256
|
-
channelConsumers.forEach((c) => broker.cancel(c.consumerTag));
|
|
257
|
-
this[kClosed] = true;
|
|
258
|
-
this[kEmitter].emit('close');
|
|
319
|
+
this._teardown();
|
|
320
|
+
this.emit('close');
|
|
259
321
|
return resolveOrCallback(callback);
|
|
260
322
|
}
|
|
261
|
-
ack(message,
|
|
262
|
-
|
|
323
|
+
ack(message, allUpTo) {
|
|
324
|
+
const deliveryTag = message.fields.deliveryTag;
|
|
325
|
+
const channelMessage = this._broker._getMessageByDeliveryTag(this._channelQueue.name, deliveryTag);
|
|
326
|
+
const channelQ = this._channelQueue;
|
|
327
|
+
|
|
328
|
+
if (!allUpTo) this._callBroker(ackMessage);
|
|
329
|
+
else this._callBroker(ackAllUpToMessage);
|
|
330
|
+
|
|
331
|
+
function ackMessage() {
|
|
332
|
+
const msg = message[kSmqp];
|
|
333
|
+
if (!channelMessage || !msg.pending) {
|
|
334
|
+
throw new FakeAmqpUnknownDeliveryTag(message.fields.deliveryTag);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
channelQ.ack(channelMessage, false);
|
|
338
|
+
this.ack(msg, false);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function ackAllUpToMessage() {
|
|
342
|
+
const msg = message[kSmqp];
|
|
343
|
+
if (!channelMessage || !msg.pending) {
|
|
344
|
+
throw new FakeAmqpUnknownDeliveryTag(message.fields.deliveryTag);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const brokerMessages = allUpToDeliveryTag(channelQ, deliveryTag, 'ack', false);
|
|
348
|
+
for (const brokerMessage of brokerMessages) {
|
|
349
|
+
brokerMessage.ack(false);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
channelQ.ack(channelMessage, false);
|
|
353
|
+
this.ack(msg, false);
|
|
354
|
+
}
|
|
263
355
|
}
|
|
264
356
|
ackAll() {
|
|
265
|
-
const
|
|
266
|
-
|
|
357
|
+
const channelQ = this._channelQueue;
|
|
358
|
+
let msg;
|
|
359
|
+
const brokerMessages = [];
|
|
360
|
+
while ((msg = channelQ.get())) {
|
|
361
|
+
brokerMessages.push(msg.content[kSmqp]);
|
|
362
|
+
msg.ack();
|
|
363
|
+
}
|
|
267
364
|
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
nack(message, ...args) {
|
|
272
|
-
if (this.connection._version >= 2.3) throw new Error(`Nack is not implemented in versions before 2.3 (${this.connection._version})`);
|
|
273
|
-
return this._broker.nack(message[kSmqp], ...args);
|
|
274
|
-
}
|
|
275
|
-
reject(message, ...args) {
|
|
276
|
-
this._broker.reject(message[kSmqp], ...args);
|
|
365
|
+
for (const brokerMessage of brokerMessages) {
|
|
366
|
+
brokerMessage.ack();
|
|
367
|
+
}
|
|
277
368
|
}
|
|
278
|
-
|
|
279
|
-
const
|
|
280
|
-
const
|
|
369
|
+
reject(message, requeue = false) {
|
|
370
|
+
const deliveryTag = message.fields.deliveryTag;
|
|
371
|
+
const channelMessage = this._broker._getMessageByDeliveryTag(this._channelQueue.name, deliveryTag);
|
|
372
|
+
const channelQ = this._channelQueue;
|
|
373
|
+
|
|
374
|
+
this._callBroker(rejectMessage);
|
|
281
375
|
|
|
282
|
-
|
|
283
|
-
|
|
376
|
+
function rejectMessage() {
|
|
377
|
+
const msg = message[kSmqp];
|
|
378
|
+
if (!channelMessage || !msg.pending) {
|
|
379
|
+
throw new FakeAmqpUnknownDeliveryTag(deliveryTag);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
channelQ.reject(channelMessage, false);
|
|
383
|
+
this.reject(msg, requeue);
|
|
384
|
+
}
|
|
284
385
|
}
|
|
285
|
-
|
|
286
|
-
this
|
|
386
|
+
nack(message, allUpTo = false, requeue = false) {
|
|
387
|
+
if (this.connection._version < 2.3) throw new Error(`Nack is not implemented in versions before 2.3 (${this.connection._version})`);
|
|
388
|
+
|
|
389
|
+
const deliveryTag = message.fields.deliveryTag;
|
|
390
|
+
const channelMessage = this._broker._getMessageByDeliveryTag(this._channelQueue.name, deliveryTag);
|
|
391
|
+
const channelQ = this._channelQueue;
|
|
392
|
+
|
|
393
|
+
if (!allUpTo) this._callBroker(nackMessage);
|
|
394
|
+
else this._callBroker(nackAllUpToMessage);
|
|
395
|
+
|
|
396
|
+
function nackMessage() {
|
|
397
|
+
const msg = message[kSmqp];
|
|
398
|
+
if (!channelMessage || !msg.pending) {
|
|
399
|
+
throw new FakeAmqpUnknownDeliveryTag(deliveryTag);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
channelQ.nack(channelMessage, false, false);
|
|
403
|
+
this.nack(msg, false, requeue);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function nackAllUpToMessage() {
|
|
407
|
+
const msg = message[kSmqp];
|
|
408
|
+
if (!channelMessage || !msg.pending) {
|
|
409
|
+
throw new FakeAmqpUnknownDeliveryTag(deliveryTag);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const brokerMessages = allUpToDeliveryTag(channelQ, deliveryTag, 'nack', false, false);
|
|
413
|
+
for (const brokerMessage of brokerMessages) {
|
|
414
|
+
brokerMessage.nack(false, requeue);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
channelMessage.nack(false, false);
|
|
418
|
+
this.nack(msg, false, requeue);
|
|
419
|
+
}
|
|
287
420
|
}
|
|
288
|
-
|
|
289
|
-
|
|
421
|
+
nackAll(requeue = true) {
|
|
422
|
+
const channelQ = this._channelQueue;
|
|
423
|
+
let msg;
|
|
424
|
+
const brokerMessages = [];
|
|
425
|
+
while ((msg = channelQ.get())) {
|
|
426
|
+
brokerMessages.push(msg.content[kSmqp]);
|
|
427
|
+
msg.reject(false);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
for (const brokerMessage of brokerMessages) {
|
|
431
|
+
brokerMessage.reject(requeue);
|
|
432
|
+
}
|
|
290
433
|
}
|
|
291
|
-
|
|
292
|
-
|
|
434
|
+
prefetch(val, isChannelPrefetch) {
|
|
435
|
+
if (this.connection._version < 3.3) {
|
|
436
|
+
if (isChannelPrefetch !== undefined) {
|
|
437
|
+
return this.connection.close();
|
|
438
|
+
}
|
|
439
|
+
this[kChannelPrefetch] = val;
|
|
440
|
+
} else {
|
|
441
|
+
if (isChannelPrefetch) {
|
|
442
|
+
this[kChannelPrefetch] = val;
|
|
443
|
+
} else {
|
|
444
|
+
this[kPrefetch] = val;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
293
447
|
}
|
|
294
448
|
_callBroker(fn, ...args) {
|
|
295
|
-
let [
|
|
449
|
+
let [poppedCb] = args.slice(-1);
|
|
296
450
|
if (typeof poppedCb === 'function') args.splice(-1);
|
|
297
451
|
else poppedCb = null;
|
|
298
452
|
|
|
@@ -306,7 +460,8 @@ class FakeAmqplibChannel {
|
|
|
306
460
|
return resolve(result);
|
|
307
461
|
} catch (err) {
|
|
308
462
|
if (err._killConnection) this.connection.close();
|
|
309
|
-
else if (err._killChannel) this
|
|
463
|
+
else if (err._killChannel) this._teardown();
|
|
464
|
+
if (err._emit) this.emit('error', err);
|
|
310
465
|
if (!poppedCb) return reject(err);
|
|
311
466
|
poppedCb(err);
|
|
312
467
|
return resolve();
|
|
@@ -315,9 +470,44 @@ class FakeAmqplibChannel {
|
|
|
315
470
|
}
|
|
316
471
|
_emitReturn({ fields, content, properties }) {
|
|
317
472
|
process.nextTick(() => {
|
|
318
|
-
this
|
|
473
|
+
this.emit('return', { fields, content, properties });
|
|
319
474
|
});
|
|
320
475
|
}
|
|
476
|
+
_createChannelMessage(smqpMessage, noAck) {
|
|
477
|
+
const deliveryTag = this._broker._getNextDeliveryTag();
|
|
478
|
+
const consumeMessage = new Message(smqpMessage, deliveryTag);
|
|
479
|
+
if (!noAck) {
|
|
480
|
+
const channelQ = this._channelQueue;
|
|
481
|
+
channelQ.queueMessage(consumeMessage.fields, consumeMessage);
|
|
482
|
+
}
|
|
483
|
+
return consumeMessage;
|
|
484
|
+
}
|
|
485
|
+
_teardown() {
|
|
486
|
+
this[kClosed] = true;
|
|
487
|
+
const channelName = this._channelName;
|
|
488
|
+
const broker = this._broker;
|
|
489
|
+
const channelConsumers = broker._getChannelConsumers(channelName);
|
|
490
|
+
channelConsumers.forEach((c) => broker.cancel(c.consumerTag));
|
|
491
|
+
|
|
492
|
+
let msg;
|
|
493
|
+
while ((msg = this._channelQueue.get())) {
|
|
494
|
+
msg.content[kSmqp].reject(true);
|
|
495
|
+
msg.reject(false);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
broker.off('return', this._emitReturn);
|
|
499
|
+
}
|
|
500
|
+
_calculateChannelCapacity(consumerCapacity) {
|
|
501
|
+
const channelPrefetch = this[kChannelPrefetch];
|
|
502
|
+
if (channelPrefetch === Infinity) return consumerCapacity;
|
|
503
|
+
|
|
504
|
+
const channelCapacity = channelPrefetch - this._channelQueue.messageCount;
|
|
505
|
+
|
|
506
|
+
let capacity = consumerCapacity;
|
|
507
|
+
if (channelCapacity <= 0) capacity = 0;
|
|
508
|
+
else if (channelCapacity < capacity) capacity = channelCapacity;
|
|
509
|
+
return capacity;
|
|
510
|
+
}
|
|
321
511
|
}
|
|
322
512
|
|
|
323
513
|
class FakeAmqplibConfirmChannel extends FakeAmqplibChannel {
|
|
@@ -325,38 +515,42 @@ class FakeAmqplibConfirmChannel extends FakeAmqplibChannel {
|
|
|
325
515
|
if (!Buffer.isBuffer(content)) throw new TypeError('content is not a buffer');
|
|
326
516
|
if (exchange === '') return this.sendToQueue(routingKey, content, options, callback);
|
|
327
517
|
|
|
328
|
-
const args = [
|
|
518
|
+
const args = [this._broker.publish, exchange, routingKey, content];
|
|
329
519
|
|
|
330
520
|
args.push(...addConfirmCallback(this._broker, options, callback));
|
|
331
521
|
|
|
332
|
-
this.checkExchange(exchange)
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
522
|
+
this.checkExchange(exchange)
|
|
523
|
+
.then(() => {
|
|
524
|
+
return this._callBroker(...args);
|
|
525
|
+
})
|
|
526
|
+
.catch((err) => {
|
|
527
|
+
this.emit('error', err);
|
|
528
|
+
});
|
|
337
529
|
|
|
338
530
|
return true;
|
|
339
531
|
}
|
|
340
532
|
sendToQueue(queue, content, options, callback) {
|
|
341
533
|
if (!Buffer.isBuffer(content)) throw new TypeError('content is not a buffer');
|
|
342
534
|
|
|
343
|
-
const args = [
|
|
535
|
+
const args = [this._broker.sendToQueue, queue, content];
|
|
344
536
|
|
|
345
537
|
args.push(...addConfirmCallback(this._broker, options, callback));
|
|
346
538
|
|
|
347
|
-
this.checkQueue(queue)
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
539
|
+
this.checkQueue(queue)
|
|
540
|
+
.then(() => {
|
|
541
|
+
return this._callBroker(...args);
|
|
542
|
+
})
|
|
543
|
+
.catch((err) => {
|
|
544
|
+
this.emit('error', err);
|
|
545
|
+
});
|
|
352
546
|
|
|
353
547
|
return true;
|
|
354
548
|
}
|
|
355
549
|
}
|
|
356
550
|
|
|
357
|
-
class FakeAmqplibConnection {
|
|
551
|
+
class FakeAmqplibConnection extends events.EventEmitter {
|
|
358
552
|
constructor(broker, version, amqpUrl) {
|
|
359
|
-
|
|
553
|
+
super();
|
|
360
554
|
this[kClosed] = false;
|
|
361
555
|
this._channels = [];
|
|
362
556
|
this._url = normalizeAmqpUrl(amqpUrl);
|
|
@@ -367,9 +561,6 @@ class FakeAmqplibConnection {
|
|
|
367
561
|
get _closed() {
|
|
368
562
|
return this[kClosed];
|
|
369
563
|
}
|
|
370
|
-
get _emitter() {
|
|
371
|
-
return this[kEmitter];
|
|
372
|
-
}
|
|
373
564
|
get connection() {
|
|
374
565
|
return {
|
|
375
566
|
serverProperties: {
|
|
@@ -403,16 +594,10 @@ class FakeAmqplibConnection {
|
|
|
403
594
|
|
|
404
595
|
this._channels.splice(0).forEach((channel) => channel.close());
|
|
405
596
|
|
|
406
|
-
this
|
|
597
|
+
this.emit('close');
|
|
407
598
|
|
|
408
599
|
return resolveOrCallback(args.slice(-1)[0]);
|
|
409
600
|
}
|
|
410
|
-
on(...args) {
|
|
411
|
-
return this[kEmitter].on(...args);
|
|
412
|
-
}
|
|
413
|
-
once(...args) {
|
|
414
|
-
return this[kEmitter].once(...args);
|
|
415
|
-
}
|
|
416
601
|
}
|
|
417
602
|
|
|
418
603
|
function FakeAmqplib(minorVersion = '3.5') {
|
|
@@ -436,14 +621,14 @@ FakeAmqplib.prototype.connect = function fakeConnect(amqpUrl, ...args) {
|
|
|
436
621
|
|
|
437
622
|
FakeAmqplib.prototype.connectSync = function fakeConnectSync(amqpUrl, ...args) {
|
|
438
623
|
const { _broker } = this.connections.find((conn) => compareConnectionString(conn._url, amqpUrl)) || {};
|
|
439
|
-
const broker = _broker || new
|
|
624
|
+
const broker = _broker || new AmqplibBroker(this);
|
|
440
625
|
const connection = new FakeAmqplibConnection(broker, this.version, amqpUrl, ...args);
|
|
441
626
|
|
|
442
627
|
const connections = this.connections;
|
|
443
628
|
|
|
444
629
|
connections.push(connection);
|
|
445
630
|
|
|
446
|
-
connection.
|
|
631
|
+
connection.once('close', () => {
|
|
447
632
|
const idx = connections.indexOf(connection);
|
|
448
633
|
if (idx > -1) connections.splice(idx, 1);
|
|
449
634
|
});
|
|
@@ -479,39 +664,26 @@ function compareConnectionString(url1, url2) {
|
|
|
479
664
|
return parsedUrl1.host === parsedUrl2.host && parsedUrl1.pathname === parsedUrl2.pathname;
|
|
480
665
|
}
|
|
481
666
|
|
|
482
|
-
function Message(smqpMessage) {
|
|
483
|
-
this[kSmqp] = smqpMessage;
|
|
484
|
-
this.content = smqpMessage.content;
|
|
485
|
-
this.fields = smqpMessage.fields;
|
|
486
|
-
this.properties = smqpMessage.properties;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
667
|
function normalizeAmqpUrl(url$1) {
|
|
490
668
|
if (!url$1) return new URL('amqp://localhost:5672/');
|
|
491
669
|
if (typeof url$1 === 'string') url$1 = new URL(url$1);
|
|
492
670
|
|
|
493
671
|
if (!(url$1 instanceof URL)) {
|
|
494
|
-
const {
|
|
495
|
-
protocol = 'amqp',
|
|
496
|
-
hostname = 'localhost',
|
|
497
|
-
port = 5672,
|
|
498
|
-
vhost = '/',
|
|
499
|
-
username,
|
|
500
|
-
password,
|
|
501
|
-
...rest
|
|
502
|
-
} = url$1;
|
|
672
|
+
const { protocol = 'amqp', hostname = 'localhost', port = 5672, vhost = '/', username, password, ...rest } = url$1;
|
|
503
673
|
let auth = username;
|
|
504
674
|
if (auth && password) {
|
|
505
675
|
auth += `:${password}`;
|
|
506
676
|
}
|
|
507
|
-
url$1 = new URL(
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
677
|
+
url$1 = new URL(
|
|
678
|
+
url.format({
|
|
679
|
+
protocol,
|
|
680
|
+
hostname,
|
|
681
|
+
port,
|
|
682
|
+
pathname: vhost,
|
|
683
|
+
slashes: true,
|
|
684
|
+
auth,
|
|
685
|
+
}),
|
|
686
|
+
);
|
|
515
687
|
|
|
516
688
|
for (const k in rest) {
|
|
517
689
|
switch (k) {
|
|
@@ -558,7 +730,27 @@ function addConfirmCallback(broker, options, callback) {
|
|
|
558
730
|
}
|
|
559
731
|
}
|
|
560
732
|
|
|
561
|
-
return [
|
|
733
|
+
return [options, confirmCallback];
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
function allUpToDeliveryTag(q, deliveryTag, op, ...args) {
|
|
737
|
+
const brokerMessages = [];
|
|
738
|
+
|
|
739
|
+
const consumer = q.consume(
|
|
740
|
+
(_, cmsg) => {
|
|
741
|
+
const msgDeliveryTag = cmsg.fields.deliveryTag;
|
|
742
|
+
if (msgDeliveryTag >= deliveryTag) {
|
|
743
|
+
return q.cancel(cmsg.fields.consumerTag);
|
|
744
|
+
}
|
|
745
|
+
brokerMessages.push(cmsg.content[kSmqp]);
|
|
746
|
+
cmsg[op](...args);
|
|
747
|
+
},
|
|
748
|
+
{ prefetch: Infinity },
|
|
749
|
+
);
|
|
750
|
+
|
|
751
|
+
consumer.cancel();
|
|
752
|
+
|
|
753
|
+
return brokerMessages;
|
|
562
754
|
}
|
|
563
755
|
|
|
564
756
|
const defaultFake = new FakeAmqplib('3.5');
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onify/fake-amqplib",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Fake amqplib",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
|
+
"types": "./index.d.ts",
|
|
7
8
|
"require": "./main.cjs",
|
|
8
9
|
"import": "./index.js"
|
|
9
10
|
},
|
|
@@ -13,7 +14,7 @@
|
|
|
13
14
|
"scripts": {
|
|
14
15
|
"test": "mocha",
|
|
15
16
|
"posttest": "npm run lint && npm run dist",
|
|
16
|
-
"lint": "eslint . --cache",
|
|
17
|
+
"lint": "eslint . --cache && prettier . -c --cache",
|
|
17
18
|
"dist": "rollup -c",
|
|
18
19
|
"prepack": "npm run dist",
|
|
19
20
|
"cov:html": "c8 -r html -r text mocha",
|
|
@@ -32,16 +33,17 @@
|
|
|
32
33
|
},
|
|
33
34
|
"license": "MIT",
|
|
34
35
|
"dependencies": {
|
|
35
|
-
"smqp": "^8.2.
|
|
36
|
+
"smqp": "^8.2.4"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
|
-
"@bonniernews/eslint-config": "^1.0.1",
|
|
39
39
|
"@rollup/plugin-commonjs": "^25.0.5",
|
|
40
40
|
"@types/amqplib": "^0.10.2",
|
|
41
|
-
"c8": "^
|
|
42
|
-
"chai": "^
|
|
43
|
-
"eslint": "^
|
|
41
|
+
"c8": "^9.1.0",
|
|
42
|
+
"chai": "^5.1.0",
|
|
43
|
+
"eslint": "^9.0.0",
|
|
44
|
+
"globals": "^15.0.0",
|
|
44
45
|
"mocha": "^10.2.0",
|
|
46
|
+
"prettier": "^3.2.5",
|
|
45
47
|
"rollup": "^4.0.2"
|
|
46
48
|
},
|
|
47
49
|
"keywords": [
|