Skip to content

Commit 0ca8250

Browse files
austin-beerabreits
authored andcommitted
Fix issues with replying to RPC messages using Promises (#44)
* Fix issues with replying to RPC messages using Promises Issue 1: If a message is received with the replyTo field set (an RPC message) and the onMessage function that's passed to activateConsumer() or startConsumer() returns a Promise and the Promise isn't an ES6 Promise, a JSON version of the Promise itself may be returned in the reply message instead of the Promise's resolved value. https://stackoverflow.com/questions/27746304/how-do-i-tell-if-an-object-is-a-promise Issue 2: If a message is received with the replyTo field set (an RPC message) and the onMessage function that's passed to startConsumer() returns a Promise, the Promise's resolved value isn't returned in the reply message. Instead a JSON version of the entire Promise is returned. * Rebuild transpiled library from Typescript source Update version information in package file to match latest released version * Allow the onMessage callback that's passed to activateConsumer() and startConsumer() to return a promise regardless of whether or not the replyTo field is set. startConsumer() can automatically ack the message. If noAck == false and manualAck == false and onMessage returns a promise, wait until the promise is resolved before acknowledging the message. * Rebuild transpiled library from Typescript source
1 parent fb19802 commit 0ca8250

File tree

3 files changed

+89
-96
lines changed

3 files changed

+89
-96
lines changed

lib/amqp-ts.d.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* methods and properties starting with '_' signify that the scope of the item should be limited to
66
* the inside of the enclosing namespace.
77
*/
8+
/// <reference types="node" />
89
import * as AmqpLib from "amqplib/callback_api";
910
import * as Promise from "bluebird";
1011
import * as winston from "winston";
@@ -31,8 +32,8 @@ export declare class Connection extends EventEmitter {
3132
[id: string]: Binding;
3233
};
3334
constructor(url?: string, socketOptions?: any, reconnectStrategy?: Connection.ReconnectStrategy);
34-
private rebuildConnection();
35-
private tryToConnect(thisConnection, retry, callback);
35+
private rebuildConnection;
36+
private tryToConnect;
3637
_rebuildAll(err: Error): Promise<void>;
3738
close(): Promise<void>;
3839
/**
@@ -48,7 +49,7 @@ export declare class Connection extends EventEmitter {
4849
declareExchange(name: string, type?: string, options?: Exchange.DeclarationOptions): Exchange;
4950
declareQueue(name: string, options?: Queue.DeclarationOptions): Queue;
5051
declareTopology(topology: Connection.Topology): Promise<any>;
51-
getConnection: AmqpLib.Connection;
52+
readonly getConnection: AmqpLib.Connection;
5253
}
5354
export declare namespace Connection {
5455
interface ReconnectStrategy {
@@ -99,8 +100,8 @@ export declare class Exchange {
99100
_options: Exchange.DeclarationOptions;
100101
_deleting: Promise<void>;
101102
_closing: Promise<void>;
102-
name: string;
103-
type: string;
103+
readonly name: string;
104+
readonly type: string;
104105
constructor(connection: Connection, name: string, type?: string, options?: Exchange.DeclarationOptions);
105106
_initialize(): void;
106107
/**
@@ -149,7 +150,7 @@ export declare class Queue {
149150
_consumerStopping: boolean;
150151
_deleting: Promise<Queue.DeleteResult>;
151152
_closing: Promise<void>;
152-
name: string;
153+
readonly name: string;
153154
constructor(connection: Connection, name: string, options?: Queue.DeclarationOptions);
154155
_initialize(): void;
155156
static _packMessageContent(content: any, options: any): Buffer;

lib/amqp-ts.js

Lines changed: 64 additions & 68 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/amqp-ts.ts

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -941,23 +941,21 @@ export class Queue {
941941
}
942942
var payload = Queue._unpackMessageContent(msg);
943943
var result = this._consumer(payload);
944-
if (!(result instanceof Promise)) {
945-
result = Promise.resolve(result);
946-
}
947-
result.then((resultValue) => {
948-
// check if there is a reply-to
949-
if (msg.properties.replyTo) {
950-
var options: any = {};
951-
resultValue = Queue._packMessageContent(resultValue, options);
952-
this._channel.sendToQueue(msg.properties.replyTo, resultValue, options);
953-
}
954-
944+
// convert the result to a promise if it isn't one already
945+
Promise.resolve(result).then((resultValue) => {
946+
// check if there is a reply-to
947+
if (msg.properties.replyTo) {
948+
var options: any = {};
949+
resultValue = Queue._packMessageContent(resultValue, options);
950+
this._channel.sendToQueue(msg.properties.replyTo, resultValue, options);
951+
}
955952
// 'hack' added to allow better manual ack control by client (less elegant, but should work)
956-
if (this._consumerOptions.manualAck !== true && this._consumerOptions.noAck !== true) {
953+
if (this._consumerOptions.manualAck !== true && this._consumerOptions.noAck !== true) {
957954
this._channel.ack(msg);
958-
}}).catch((err) => {
959-
log.log("error", "Queue.onMessage RPC promise returned error: " + err.message, { module: "amqp-ts" });
960-
});
955+
}
956+
}).catch((err) => {
957+
log.log("error", "Queue.onMessage RPC promise returned error: " + err.message, { module: "amqp-ts" });
958+
});
961959
} catch (err) {
962960
/* istanbul ignore next */
963961
log.log("error", "Queue.onMessage consumer function returned error: " + err.message, { module: "amqp-ts" });
@@ -980,11 +978,9 @@ export class Queue {
980978
message._message = msg;
981979
message._channel = this._channel;
982980
var result = this._consumer(message);
983-
if (!(result instanceof Promise)) {
984-
result = Promise.resolve(result);
985-
}
986-
result.then((resultValue) => {
987-
// check if there is a reply-to
981+
// convert the result to a promise if it isn't one already
982+
Promise.resolve(result).then((resultValue) => {
983+
// check if there is a reply-to
988984
if (msg.properties.replyTo) {
989985
if (!(resultValue instanceof Message)) {
990986
resultValue = new Message(resultValue, {});
@@ -993,8 +989,8 @@ export class Queue {
993989
this._channel.sendToQueue(msg.properties.replyTo, resultValue.content, resultValue.properties);
994990
}
995991
}).catch((err) => {
996-
log.log("error", "Queue.onMessage RPC promise returned error: " + err.message, { module: "amqp-ts" });
997-
});
992+
log.log("error", "Queue.onMessage RPC promise returned error: " + err.message, { module: "amqp-ts" });
993+
});
998994
} catch (err) {
999995
/* istanbul ignore next */
1000996
log.log("error", "Queue.onMessage consumer function returned error: " + err.message, { module: "amqp-ts" });

0 commit comments

Comments
 (0)