Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Service Bus] Renames to use the messages suffix and remove singular alternatives #9678

Merged
merged 6 commits into from
Jun 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions sdk/servicebus/service-bus/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,12 @@ This gives you a sender which you can use to [send][sender_send] messages.
const sender = serviceBusClient.createSender("my-queue");

// sending a single message
await sender.send({
await sender.sendMessages({
body: "my-message-body"
});

// sending multiple messages
await sender.send([
await sender.sendMessages([
{
body: "my-message-body"
},
Expand All @@ -124,7 +124,7 @@ await sender.send([
### Receive messages

Once you have created an instance of a `ServiceBusClient` class, you can get a `Receiver`
using the [createReceiver][sbclient_createreceiver] function.
using the [createReceiver][sbclient_createreceiver] method.

```javascript
const receiver = serviceBusClient.createReceiver("my-queue", "peekLock");
Expand All @@ -134,11 +134,11 @@ You can use this receiver in one of 3 ways to receive messages:

#### Get an array of messages

Use the [receiveBatch][receiverreceivebatch] function which returns a promise that
Use the [receiveMessages][receiverreceivebatch] function which returns a promise that
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[receiverreceivebatch] will need to change and I think that'll also require a change to the URLs to the docs as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left this as is because it would point to a broken link. Since we do a clean up of links when we get closer to release, we could do it then.

resolves to an array of messages.

```javascript
const myMessages = await receiver.receiveBatch(10);
const myMessages = await receiver.receiveMessages(10);
```

#### Subscribe using a message handler
Expand Down Expand Up @@ -191,7 +191,7 @@ your message lands in the right session.

```javascript
const sender = serviceBusClient.createSender("my-session-queue");
await sender.send({
await sender.sendMessages({
body: "my-message-body",
sessionId: "my-session"
});
Expand Down
42 changes: 28 additions & 14 deletions sdk/servicebus/service-bus/migrationguide.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ brings this package in line with the [Azure SDK Design Guidelines for Typescript

## API changes from V1 to V7

### Creating ServiceBusClient

- `ServiceBusClient` can now be constructed using new(). The static methods to
construct it have been removed.

Expand All @@ -27,6 +29,8 @@ brings this package in line with the [Azure SDK Design Guidelines for Typescript
const serviceBusClient = new ServiceBusClient("connection string");
```

### Creating senders and receivers

- `QueueClient`, `TopicClient` and `SubscriptionClient` have been replaced with methods to
create receivers and senders directly from `ServiceBusClient`.

Expand Down Expand Up @@ -67,6 +71,20 @@ brings this package in line with the [Azure SDK Design Guidelines for Typescript
const subscriptionReceiver = serviceBusClient.createReceiver("topic", "subscription", "peekLock");
```

- `createSessionReceiver()` is now an async method.
- The promise returned by this method is resolved when a receiver link has been initialized with a session in the service.
- Prior to v7 `createSessionReceiver()` worked using lazy-initialization, where the
receiver link to the session was only initialized when the async methods on the `SessionReceiver`
were first called.

### Receiving messages

* `peek()` and `peekBySequenceNumber()` methods are collapsed into a single method `peekMessages()`.
The options passed to this new method accomodates both number of messages to be peeked and the sequence number to peek from.

* `receiveBatch()` method is renamed to `receiveMessages()` to be consistent in usage of the `Messages` suffix in other methods
on the receiver and the sender.

* `registerMessageHandler` on `Receiver` has been renamed to `subscribe` and takes different arguments.

In V1:
Expand All @@ -87,32 +105,28 @@ brings this package in line with the [Azure SDK Design Guidelines for Typescript
});
```

* `peekBySequenceNumber()`is removed in favor of an overload to `peekMessages()` that would take the sequence number to start peeking from in the options.
### Rule management

* Subscription rule management has been moved to its own class, rather than being part of the now-removed `SubscriptionClient`
* The add/get/remove rule operations on the older `SubscriptionClient` have moved to the new `ServiceBusManagementClient` class which will be supporting
Create, Get, Update and Delete operations on Queues, Topics, Subscriptions and Rules.

In V1:

```typescript
subscriptionClient.addRule();
subscriptionClient.getRules();
subscriptionClient.removeRule();
await subscriptionClient.addRule();
await subscriptionClient.getRules();
await subscriptionClient.removeRule();
```

In V7:

```typescript
const ruleManager = serviceBusClient.getSubscriptionRuleManager("topic", "subscription");
ruleManager.addRule();
ruleManager.getRules();
ruleManager.removeRule();
const serviceBusManagementClient = new ServiceBusManagementClient(connectionString);
await serviceBusManagementClient.createRule();
await serviceBusManagementClient.getRules();
await serviceBusManagementClient.deleteRule();
```

* createSessionReceiver() is now an async method. The promise returned by this method
is resolved when a receiver link has been initialized with a session in the service.

Prior to v7 `createSessionReceiver()` worked using lazy-initialization, where the
receiver link to the session was only initialized when the async methods on the `SessionReceiver`
were first called.

![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-js%2Fsdk%2Fservicebus%2Fservice-bus%2FMIGRATIONGUIDE.png)
23 changes: 9 additions & 14 deletions sdk/servicebus/service-bus/review/service-bus.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,6 @@ export interface QueuesResponse extends Array<QueueDescription>, Response {
export interface QueuesRuntimeInfoResponse extends Array<QueueRuntimeInfo>, Response {
}

// @public
export interface ReceiveBatchOptions extends OperationOptions, WaitTimeOptions {
}

// @public
export interface ReceivedMessage extends ServiceBusMessage {
readonly _amqpMessage: AmqpMessage;
Expand Down Expand Up @@ -207,6 +203,10 @@ export interface ReceivedMessageWithLock extends ReceivedMessage {
renewLock(): Promise<Date>;
}

// @public
export interface ReceiveMessagesOptions extends OperationOptions, WaitTimeOptions {
}

// @public
export interface Receiver<ReceivedMessageT> {
close(): Promise<void>;
Expand All @@ -215,9 +215,8 @@ export interface Receiver<ReceivedMessageT> {
isClosed: boolean;
isReceivingMessages(): boolean;
peekMessages(options?: PeekMessagesOptions): Promise<ReceivedMessage[]>;
receiveBatch(maxMessages: number, options?: ReceiveBatchOptions): Promise<ReceivedMessageT[]>;
receiveDeferredMessage(sequenceNumber: Long, options?: OperationOptions): Promise<ReceivedMessageT | undefined>;
receiveDeferredMessages(sequenceNumbers: Long[], options?: OperationOptions): Promise<ReceivedMessageT[]>;
receiveDeferredMessages(sequenceNumbers: Long | Long[], options?: OperationOptions): Promise<ReceivedMessageT[]>;
receiveMessages(maxMessages: number, options?: ReceiveMessagesOptions): Promise<ReceivedMessageT[]>;
receiveMode: "peekLock" | "receiveAndDelete";
subscribe(handlers: MessageHandlers<ReceivedMessageT>, options?: SubscribeOptions): void;
}
Expand Down Expand Up @@ -246,18 +245,14 @@ export interface RulesResponse extends Array<RuleDescription>, Response {

// @public
export interface Sender {
cancelScheduledMessage(sequenceNumber: Long, options?: OperationOptions): Promise<void>;
cancelScheduledMessages(sequenceNumbers: Long[], options?: OperationOptions): Promise<void>;
cancelScheduledMessages(sequenceNumbers: Long | Long[], options?: OperationOptions): Promise<void>;
close(): Promise<void>;
createBatch(options?: CreateBatchOptions): Promise<ServiceBusMessageBatch>;
entityPath: string;
isClosed: boolean;
open(options?: SenderOpenOptions): Promise<void>;
scheduleMessage(scheduledEnqueueTimeUtc: Date, message: ServiceBusMessage, options?: OperationOptions): Promise<Long>;
scheduleMessages(scheduledEnqueueTimeUtc: Date, messages: ServiceBusMessage[], options?: OperationOptions): Promise<Long[]>;
send(message: ServiceBusMessage, options?: OperationOptions): Promise<void>;
send(messages: ServiceBusMessage[], options?: OperationOptions): Promise<void>;
send(messageBatch: ServiceBusMessageBatch, options?: OperationOptions): Promise<void>;
Comment on lines -258 to -260
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced overloads for send() with input parameter supporting union type to be consistent with how we are dealing with other methods that take both single & multi items

Why not retain this send as

    sendMessages(message: ServiceBusMessage, options?: OperationOptions): Promise<void>;
    sendMessages(messages: ServiceBusMessage[], options?: OperationOptions): Promise<void>;
    sendMessages(messageBatch: ServiceBusMessageBatch, options?: OperationOptions): Promise<void>;

and add the new ones as follows?

    receiveDeferredMessages(sequenceNumber: Long, options?: OperationOptions): Promise<ReceivedMessageT[]>;
    receiveDeferredMessages(sequenceNumbers: Long[], options?: OperationOptions): Promise<ReceivedMessageT[]>;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is up for debate and the final result should probably go to our guidelines :)

Personally, I like the single method model because it reduces clutter in the editor suggestions. I'd rather see a single receiveDeferredMessages in my suggestions and then when I add the ( see that I can pass either a single value or an array, instead of seeing the two suggestions, making me pause and think as to which ones I should be using.

From a API reference docs perspective, it is one less method to document if we don't follow the overloads pattern.

cc @xirzec, @bterlson, @chradek

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also dislike overloads since we don't really have them. :)

Is it really that useful to support both singular and array call patterns? Arrays are cheap in JS, so my default is to say only take an array and someone can box a singular value if they need to.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it really that useful to support both singular and array call patterns?

I like removing singular :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Event Hubs we just have a single sendBatch method that accepts either a batch or an array of events and don't have a single event overload. I'm also in favor of removing the singular call pattern if the suffix is "messages" since that is plural :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so my default is to say only take an array and someone can box a singular value if they need to.

What benefit do we get by doing this vs having the signature reflect union type?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xirzec - from discussions in the team, sending single messages (ie, dispatching commands) is a common enough pattern in ServiceBus that we want to support it without any extra work, small as it might be.

This is in contract to EventHubs where we were (and are) pretty sure that sending large batches of messages to optimize throughput was more common.

scheduleMessages(scheduledEnqueueTimeUtc: Date, messages: ServiceBusMessage | ServiceBusMessage[], options?: OperationOptions): Promise<Long[]>;
sendMessages(messages: ServiceBusMessage | ServiceBusMessage[] | ServiceBusMessageBatch, options?: OperationOptions): Promise<void>;
}

// @public
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT Licence.

This sample demonstrates how the scheduleMessage() function can be used to schedule messages to
This sample demonstrates how the scheduleMessages() function can be used to schedule messages to
appear on a Service Bus Queue/Subscription at a later time.

See https://docs.microsoft.com/en-us/azure/service-bus-messaging/message-sequencing#scheduled-messages
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ async function sendMessages() {
promises.push(
delay(Math.random() * 30).then(async () => {
try {
await sender.send(message);
await sender.sendMessages(message);
console.log("Sent message step:", data[index].step);
} catch (err) {
console.log("Error while sending message", err);
Expand Down Expand Up @@ -121,7 +121,7 @@ async function receiveMessage() {
while (deferredSteps.size > 0) {
const step = lastProcessedRecipeStep + 1;
const sequenceNumber = deferredSteps.get(step);
const message = await receiver.receiveDeferredMessage(sequenceNumber);
const [message] = await receiver.receiveDeferredMessages(sequenceNumber);
if (message) {
console.log("Process deferred message:", message.body);
await message.complete();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ async function sendMessage() {
contentType: "application/json",
label: "Recipe"
};
await sender.send(message);
await sender.sendMessages(message);
await sender.close();
}

async function receiveMessage() {
// If receiving from a subscription you can use the createReceiver(topic, subscription) overload
const receiver = sbClient.createReceiver(queueName, "peekLock");

const messages = await receiver.receiveBatch(1);
const messages = await receiver.receiveMessages(1);

if (messages.length) {
console.log(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ async function processDeadletterMessageQueue() {
// If connecting to a subscription's dead letter queue you can use the createDeadLetterReceiver(topic, subscription) overload
const receiver = sbClient.createDeadLetterReceiver(queueName, "peekLock");

const messages = await receiver.receiveBatch(1);
const messages = await receiver.receiveMessages(1);

if (messages.length > 0) {
console.log(">>>>> Received the message from DLQ - ", messages[0].body);
Expand All @@ -62,7 +62,7 @@ async function fixAndResendMessage(oldMessage) {

console.log(">>>>> Cloning the message from DLQ and resending it - ", oldMessage.body);

await sender.send(repairedMessage);
await sender.sendMessages(repairedMessage);
await sender.close();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ async function sendMessagesForSession(shoppingEvents, sessionId) {
body: shoppingEvents[index],
label: "Shopping Step"
};
await sender.send(message);
await sender.sendMessages(message);
}
await sender.close();
}
Expand All @@ -103,7 +103,7 @@ async function processMessageFromSession(sessionId) {
sessionId
});

const messages = await sessionReceiver.receiveBatch(1, {
const messages = await sessionReceiver.receiveMessages(1, {
maxWaitTimeSeconds: 10
});
// Custom logic for processing the messages
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
**NOTE**: If you are using version 1.1.x or lower, then please use the link below:
https://github.com/Azure/azure-sdk-for-js/tree/%40azure/service-bus_1.1.5/sdk/servicebus/service-bus/samples

This sample demonstrates how the receiveBatch() function can be used to receive Service Bus
This sample demonstrates how the receiveMessages() function can be used to receive Service Bus
messages in a loop.

Setup: Please run "sendMessages.ts" sample before running this to populate the queue/topic
Expand All @@ -27,7 +27,7 @@ async function main() {

try {
for (let i = 0; i < 10; i++) {
const messages = await queueReceiver.receiveBatch(1, {
const messages = await queueReceiver.receiveMessages(1, {
maxWaitTimeSeconds: 5
});
if (!messages.length) {
Expand Down
4 changes: 2 additions & 2 deletions sdk/servicebus/service-bus/samples/javascript/sendMessages.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
**NOTE**: If you are using version 1.1.x or lower, then please use the link below:
https://github.com/Azure/azure-sdk-for-js/tree/%40azure/service-bus_1.1.5/sdk/servicebus/service-bus/samples

This sample demonstrates how the send() function can be used to send messages to Service Bus
This sample demonstrates how the sendMessages() method can be used to send messages to Service Bus
Queue/Topic.

See https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-queues-topics-subscriptions
Expand Down Expand Up @@ -48,7 +48,7 @@ async function main() {
};

console.log(`Sending message: ${message.body} - ${message.label}`);
await sender.send(message);
await sender.sendMessages(message);
}

await sender.close();
Expand Down
2 changes: 1 addition & 1 deletion sdk/servicebus/service-bus/samples/javascript/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ async function sendMessage(sbClient, scientist, sessionId) {
};

console.log(`Sending message: "${message.body}" to "${sessionId}"`);
await sender.send(message);
await sender.sendMessages(message);

await sender.close();
}
Expand Down
2 changes: 1 addition & 1 deletion sdk/servicebus/service-bus/samples/javascript/useProxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ async function main() {

console.log(`Sending message using proxy server ${proxyInfo}`);

await sender.send({
await sender.sendMessages({
body: "sample message"
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ async function sendMessages() {
promises.push(
delay(Math.random() * 30).then(async () => {
try {
await sender.send(message);
await sender.sendMessages(message);
console.log("Sent message step:", data[index].step);
} catch (err) {
console.log("Error while sending message", err);
Expand Down Expand Up @@ -124,7 +124,7 @@ async function receiveMessage() {
while (deferredSteps.size > 0) {
const step = lastProcessedRecipeStep + 1;
const sequenceNumber = deferredSteps.get(step);
const message = await receiver.receiveDeferredMessage(sequenceNumber);
const [message] = await receiver.receiveDeferredMessages(sequenceNumber);
if (message) {
console.log("Process deferred message:", message.body);
await message.complete();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ async function sendMessage() {
contentType: "application/json",
label: "Recipe"
};
await sender.send(message);
await sender.sendMessages(message);
await sender.close();
}

async function receiveMessage() {
// If receiving from a subscription you can use the createReceiver(topic, subscription) overload
const receiver = sbClient.createReceiver(queueName, "peekLock");

const messages = await receiver.receiveBatch(1);
const messages = await receiver.receiveMessages(1);

if (messages.length) {
console.log(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ async function processDeadletterMessageQueue() {
// If connecting to a subscription's dead letter queue you can use the createDeadLetterReceiver(topic, subscription) overload
const receiver = sbClient.createDeadLetterReceiver(queueName, "peekLock");

const messages = await receiver.receiveBatch(1);
const messages = await receiver.receiveMessages(1);

if (messages.length > 0) {
console.log(">>>>> Received the message from DLQ - ", messages[0].body);
Expand All @@ -64,7 +64,7 @@ async function fixAndResendMessage(oldMessage: ServiceBusMessage) {

console.log(">>>>> Cloning the message from DLQ and resending it - ", oldMessage.body);

await sender.send(repairedMessage);
await sender.sendMessages(repairedMessage);
await sender.close();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ async function sendMessagesForSession(shoppingEvents: any[], sessionId: string)
body: shoppingEvents[index],
label: "Shopping Step"
};
await sender.send(message);
await sender.sendMessages(message);
}
await sender.close();
}
Expand All @@ -120,7 +120,7 @@ async function processMessageFromSession(sessionId: string) {
sessionId
});

const messages = await sessionReceiver.receiveBatch(1, {
const messages = await sessionReceiver.receiveMessages(1, {
maxWaitTimeInMs: 10000
});

Expand Down
Loading