Skip to content

Commit 3fdbbd5

Browse files
authored
Multiple fixes and updates to rhea-promise (#44)
* Added id to the session object and improved log statements * add closeSync flavored methods to Link and Session * simplify the closeSync version. * rectify the example * Handle connection getting disconnected while closing the link, session or connection itself. * handle connection disconnects while creating a session, sender or receiver. * update readme * Added asynchronous sender * refactor code * updated changelog * addressed review feedback * remove closeSync() * address review feedback * Awaitable Sender * fix casing * Log the protocol error since rhea does not pass that error to the context in disconnected event handler * improve logs * updates as per code review * improved log statement and updated min. version of rhea to 1.0.8
1 parent 6f1a916 commit 3fdbbd5

19 files changed

+847
-160
lines changed

.vscode/launch.json

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,32 @@
77
{
88
"type": "node",
99
"request": "launch",
10-
"name": "examples",
10+
"name": "awaitableSend",
11+
"program": "${workspaceFolder}/examples/awaitableSend.ts",
12+
"outFiles": [
13+
"${workspaceFolder}/dist/**/*.js"
14+
],
15+
"envFile": "${workspaceFolder}/.env" // You can take a look at the sample.env file for supported environment variables.
16+
},
17+
{
18+
"type": "node",
19+
"request": "launch",
20+
"name": "send",
1121
"program": "${workspaceFolder}/examples/send.ts",
1222
"outFiles": [
1323
"${workspaceFolder}/dist/**/*.js"
1424
],
1525
"envFile": "${workspaceFolder}/.env" // You can take a look at the sample.env file for supported environment variables.
26+
},
27+
{
28+
"type": "node",
29+
"request": "launch",
30+
"name": "receive",
31+
"program": "${workspaceFolder}/examples/receive.ts",
32+
"outFiles": [
33+
"${workspaceFolder}/dist/**/*.js"
34+
],
35+
"envFile": "${workspaceFolder}/.env" // You can take a look at the sample.env file for supported environment variables.
1636
}
1737
]
1838
}

README.md

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# rhea-promise
22

3-
A Promisified layer over rhea AMQP client.
3+
A Promisified layer over [rhea](https://githhub.com/amqp/rhea) AMQP client.
44

55
## Pre-requisite ##
66
- **Node.js version: 6.x or higher.**
@@ -73,7 +73,7 @@ We believe our design enforces good practices to be followed while using the eve
7373
Please take a look at the [sample.env](https://github.com/amqp/rhea-promise/blob/master/sample.env) file for examples on how to provide the values for different
7474
parameters like host, username, password, port, senderAddress, receiverAddress, etc.
7575
76-
#### Sending a message.
76+
#### Sending a message via `Sender`.
7777
- Running the example from terminal: `> ts-node ./examples/send.ts`.
7878
7979
**NOTE:** If you are running the sample with `.env` config file, then please run the sample from the directory that contains `.env` config file.
@@ -130,8 +130,79 @@ async function main(): Promise<void> {
130130
message_id: "12343434343434"
131131
};
132132
133-
const delivery: Delivery = await sender.send(message);
134-
console.log(">>>>>[%s] Delivery id: ", connection.id, delivery.id);
133+
// Please, note that we are not awaiting on sender.send()
134+
// You will notice that `delivery.settled` will be `false`.
135+
const delivery: Delivery = sender.send(message);
136+
console.log(">>>>>[%s] Delivery id: %d, settled: %s",
137+
connection.id,
138+
delivery.id,
139+
delivery.settled);
140+
141+
await sender.close();
142+
await connection.close();
143+
}
144+
145+
main().catch((err) => console.log(err));
146+
```
147+
148+
### Sending a message via `AwaitableSender`
149+
- Running the example from terminal: `> ts-node ./examples/awaitableSend.ts`.
150+
151+
```typescript
152+
import {
153+
Connection, Message, ConnectionOptions, Delivery, AwaitableSenderOptions, AwaitableSender
154+
} from "rhea-promise";
155+
156+
import * as dotenv from "dotenv"; // Optional for loading environment configuration from a .env (config) file
157+
dotenv.config();
158+
159+
const host = process.env.AMQP_HOST || "host";
160+
const username = process.env.AMQP_USERNAME || "sharedAccessKeyName";
161+
const password = process.env.AMQP_PASSWORD || "sharedAccessKeyValue";
162+
const port = parseInt(process.env.AMQP_PORT || "5671");
163+
const senderAddress = process.env.SENDER_ADDRESS || "address";
164+
165+
async function main(): Promise<void> {
166+
const connectionOptions: ConnectionOptions = {
167+
transport: "tls",
168+
host: host,
169+
hostname: host,
170+
username: username,
171+
password: password,
172+
port: port,
173+
reconnect: false
174+
};
175+
const connection: Connection = new Connection(connectionOptions);
176+
const senderName = "sender-1";
177+
const awaitableSenderOptions: AwaitableSenderOptions = {
178+
name: senderName,
179+
target: {
180+
address: senderAddress
181+
},
182+
sendTimeoutInSeconds: 10
183+
};
184+
185+
await connection.open();
186+
// Notice that we are awaiting on the message being sent.
187+
const sender: AwaitableSender = await connection.createAwaitableSender(
188+
awaitableSenderOptions
189+
);
190+
191+
for (let i = 0; i < 10; i++) {
192+
const message: Message = {
193+
body: `Hello World - ${i}`,
194+
message_id: i
195+
};
196+
// Note: Here we are awaiting for the send to complete.
197+
// You will notice that `delivery.settled` will be `true`, irrespective of whether the promise resolves or rejects.
198+
const delivery: Delivery = await sender.send(message);
199+
console.log(
200+
"[%s] await sendMessage -> Delivery id: %d, settled: %s",
201+
connection.id,
202+
delivery.id,
203+
delivery.settled
204+
);
205+
}
135206
136207
await sender.close();
137208
await connection.close();
@@ -222,3 +293,7 @@ npm i
222293
```
223294
npm run build
224295
```
296+
297+
298+
## AMQP Protocol specification
299+
Amqp protocol specification can be found [here](http://www.amqp.org/sites/amqp.org/files/amqp.pdf).

changelog.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
### 1.0.0 - 2019-06-18
2+
- Updated minimum version of `rhea` to `^1.0.8`.
3+
- Added a read only property `id` to the `Session` object. The id property is created by concatenating session's local channel, remote channel and the connection id `"local-<number>_remote-<number>_<connection-id>"`, thus making it unique for that connection.
4+
- Improved log statements by adding the session `id` and the sender, receiver `name` to help while debugging applications.
5+
- Added `options` to `Link.close({closeSession: true | false})`, thus the user can specify whether the underlying session should be closed while closing the `Sender|Receiver`. Default is `true`.
6+
- Improved `open` and `close` operations on `Connection`, `Session` and `Link` by creating timer in case the connection gets disconnected. Fixes [#41](https://github.com/amqp/rhea-promise/issues/41).
7+
- The current `Sender` does not have a provision of **"awaiting"** on sending a message. The user needs to add handlers on the `Sender` for `accepted`, `rejected`, `released`, `modified` to ensure whether the message was successfully sent.
8+
Now, we have added a new `AwaitableSender` which adds the handlers internally and provides an **awaitable** `send()` operation to the customer. Fixes [#45](https://github.com/amqp/rhea-promise/issues/45).
9+
- Exporting new Errors:
10+
- `InsufficientCreditError`: Defines the error that occurs when the Sender does not have enough credit.
11+
- `SendOperationFailedError`: Defines the error that occurs when the Sender fails to send a message.
12+
113
### 0.2.0 - 2019-05-17
214
- Updated `OperationTimeoutError` to be a non-AMQP Error as pointed out in [#42](https://github.com/amqp/rhea-promise/issues/42). Fixed in [PR](https://github.com/amqp/rhea-promise/pull/43).
315

examples/awaitableSend.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the Apache License. See License in the project root for license information.
3+
4+
import {
5+
Connection,
6+
Message,
7+
ConnectionOptions,
8+
Delivery,
9+
AwaitableSenderOptions,
10+
AwaitableSender
11+
} from "../lib";
12+
13+
import * as dotenv from "dotenv"; // Optional for loading environment configuration from a .env (config) file
14+
dotenv.config();
15+
16+
const host = process.env.AMQP_HOST || "host";
17+
const username = process.env.AMQP_USERNAME || "sharedAccessKeyName";
18+
const password = process.env.AMQP_PASSWORD || "sharedAccessKeyValue";
19+
const port = parseInt(process.env.AMQP_PORT || "5671");
20+
const senderAddress = process.env.SENDER_ADDRESS || "address";
21+
22+
async function main(): Promise<void> {
23+
const connectionOptions: ConnectionOptions = {
24+
transport: "tls",
25+
host: host,
26+
hostname: host,
27+
username: username,
28+
password: password,
29+
port: port,
30+
reconnect: false
31+
};
32+
const connection: Connection = new Connection(connectionOptions);
33+
const senderName = "sender-1";
34+
const senderOptions: AwaitableSenderOptions = {
35+
name: senderName,
36+
target: {
37+
address: senderAddress
38+
},
39+
sendTimeoutInSeconds: 10
40+
};
41+
42+
await connection.open();
43+
const sender: AwaitableSender = await connection.createAwaitableSender(
44+
senderOptions
45+
);
46+
47+
for (let i = 0; i < 10; i++) {
48+
const message: Message = {
49+
body: `Hello World - ${i}`,
50+
message_id: i
51+
};
52+
// Please, note that we are awaiting on sender.send() to complete.
53+
// You will notice that `delivery.settled` will be `true`, irrespective of whether the promise resolves or rejects.
54+
const delivery: Delivery = await sender.send(message);
55+
console.log(
56+
"[%s] await sendMessage -> Delivery id: %d, settled: %s",
57+
connection.id,
58+
delivery.id,
59+
delivery.settled
60+
);
61+
}
62+
63+
await sender.close();
64+
await connection.close();
65+
}
66+
67+
main().catch((err) => console.log(err));

examples/send.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@
22
// Licensed under the Apache License. See License in the project root for license information.
33

44
import {
5-
Connection, Sender, EventContext, Message, ConnectionOptions, Delivery, SenderOptions
5+
Connection,
6+
Sender,
7+
EventContext,
8+
Message,
9+
ConnectionOptions,
10+
Delivery,
11+
SenderOptions
612
} from "../lib";
713

814
import * as dotenv from "dotenv"; // Optional for loading environment configuration from a .env (config) file
@@ -34,15 +40,23 @@ async function main(): Promise<void> {
3440
onError: (context: EventContext) => {
3541
const senderError = context.sender && context.sender.error;
3642
if (senderError) {
37-
console.log(">>>>> [%s] An error occurred for sender '%s': %O.",
38-
connection.id, senderName, senderError);
43+
console.log(
44+
">>>>> [%s] An error occurred for sender '%s': %O.",
45+
connection.id,
46+
senderName,
47+
senderError
48+
);
3949
}
4050
},
4151
onSessionError: (context: EventContext) => {
4252
const sessionError = context.session && context.session.error;
4353
if (sessionError) {
44-
console.log(">>>>> [%s] An error occurred for session of sender '%s': %O.",
45-
connection.id, senderName, sessionError);
54+
console.log(
55+
">>>>> [%s] An error occurred for session of sender '%s': %O.",
56+
connection.id,
57+
senderName,
58+
sessionError
59+
);
4660
}
4761
}
4862
};
@@ -54,8 +68,15 @@ async function main(): Promise<void> {
5468
message_id: "12343434343434"
5569
};
5670

57-
const delivery: Delivery = await sender.send(message);
58-
console.log(">>>>>[%s] Delivery id: ", connection.id, delivery.id);
71+
// Please, note that we are not awaiting on sender.send()
72+
// You will notice that `delivery.settled` will be `false`.
73+
const delivery: Delivery = sender.send(message);
74+
console.log(
75+
">>>>>[%s] send -> Delivery id: %d, settled: %s",
76+
connection.id,
77+
delivery.id,
78+
delivery.settled
79+
);
5980

6081
await sender.close();
6182
await connection.close();

0 commit comments

Comments
 (0)