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] AdminClient: ForwardTo wasn't applying on update due to bad property ordering in XML #14692

Merged
13 commits merged into from
Apr 5, 2021
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ import {
*/
export function buildQueueOptions(queue: CreateQueueOptions): InternalQueueOptions {
return {
// NOTE: this ordering is extremely important. As an example, misordering of the ForwardTo property
// resulted in a customer bug where the Forwarding attributes appeared to be set but the portal was
// not picking up on it.
richardpark-msft marked this conversation as resolved.
Show resolved Hide resolved
//
// The authority on this ordering is here:
// https://github.com/Azure/azure-sdk-for-net/blob/8af2dfc32c96ef3e340f9d20013bf588d97ea756/sdk/servicebus/Azure.Messaging.ServiceBus/src/Administration/QueuePropertiesExtensions.cs#L20

LockDuration: queue.lockDuration,
MaxSizeInMegabytes: getStringOrUndefined(queue.maxSizeInMegabytes),
RequiresDuplicateDetection: getStringOrUndefined(queue.requiresDuplicateDetection),
Expand All @@ -42,11 +49,12 @@ export function buildQueueOptions(queue: CreateQueueOptions): InternalQueueOptio
EnableBatchedOperations: getStringOrUndefined(queue.enableBatchedOperations),
AuthorizationRules: getRawAuthorizationRules(queue.authorizationRules),
Status: getStringOrUndefined(queue.status),
ForwardTo: getStringOrUndefined(queue.forwardTo),
UserMetadata: getStringOrUndefined(queue.userMetadata),
AutoDeleteOnIdle: getStringOrUndefined(queue.autoDeleteOnIdle),
EnablePartitioning: getStringOrUndefined(queue.enablePartitioning),
ForwardDeadLetteredMessagesTo: getStringOrUndefined(queue.forwardDeadLetteredMessagesTo),
ForwardTo: getStringOrUndefined(queue.forwardTo),
UserMetadata: getStringOrUndefined(queue.userMetadata),

ramya-rao-a marked this conversation as resolved.
Show resolved Hide resolved
EntityAvailabilityStatus: getStringOrUndefined(queue.availabilityStatus),
EnableExpress: getStringOrUndefined(queue.enableExpress)
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ export function buildSubscriptionOptions(
subscription: CreateSubscriptionOptions
): InternalSubscriptionOptions {
return {
// NOTE: this ordering is extremely important. As an example, misordering of the ForwardTo property
// resulted in a customer bug where the Forwarding attributes appeared to be set but the portal was
// not picking up on it.
//
// The authority on this ordering is here:
// https://github.com/Azure/azure-sdk-for-net/blob/8af2dfc32c96ef3e340f9d20013bf588d97ea756/sdk/servicebus/Azure.Messaging.ServiceBus/src/Administration/SubscriptionPropertiesExtensions.cs#L191
LockDuration: subscription.lockDuration,
RequiresSession: getStringOrUndefined(subscription.requiresSession),
DefaultMessageTimeToLive: getStringOrUndefined(subscription.defaultMessageTimeToLive),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,19 @@ import {
*/
export function buildTopicOptions(topic: CreateTopicOptions): InternalTopicOptions {
return {
// NOTE: this ordering is extremely important. As an example, misordering of the ForwardTo property
// resulted in a customer bug where the Forwarding attributes appeared to be set but the portal was
// not picking up on it.
//
// The authority on this ordering is here:
// https://github.com/Azure/azure-sdk-for-net/blob/8af2dfc32c96ef3e340f9d20013bf588d97ea756/sdk/servicebus/Azure.Messaging.ServiceBus/src/Administration/TopicPropertiesExtensions.cs#L175

DefaultMessageTimeToLive: topic.defaultMessageTimeToLive,
MaxSizeInMegabytes: getStringOrUndefined(topic.maxSizeInMegabytes),
RequiresDuplicateDetection: getStringOrUndefined(topic.requiresDuplicateDetection),
DuplicateDetectionHistoryTimeWindow: topic.duplicateDetectionHistoryTimeWindow,
EnableBatchedOperations: getStringOrUndefined(topic.enableBatchedOperations),
// TODO: in .net, but not in here: FilteringMessagesBeforePublishing
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these TODOs meant to track adding these fields? Can we create an issue for them?

Copy link
Member

@HarshaNalluru HarshaNalluru Apr 5, 2021

Choose a reason for hiding this comment

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

I'll log an issue for us for this and the one below and remove the comment.

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// TODO: in .net, but not in here: FilteringMessagesBeforePublishing

HarshaNalluru marked this conversation as resolved.
Show resolved Hide resolved
AuthorizationRules: getRawAuthorizationRules(topic.authorizationRules),
Status: getStringOrUndefined(topic.status),
UserMetadata: getStringOrUndefined(topic.userMetadata),
Expand Down
80 changes: 79 additions & 1 deletion sdk/servicebus/service-bus/test/public/atomManagement.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ import { ServiceBusAdministrationClient, WithResponse } from "../../src";
import { EntityStatus, EntityAvailabilityStatus } from "../../src";
import { EnvVarNames, getEnvVars } from "./utils/envVarUtils";
import { recreateQueue, recreateSubscription, recreateTopic } from "./utils/managementUtils";
import { EntityNames } from "./utils/testUtils";
import { EntityNames, TestClientType } from "./utils/testUtils";
import { TestConstants } from "./testConstants";
import { AzureNamedKeyCredential } from "@azure/core-auth";
import { createServiceBusClientForTests, ServiceBusClientForTests } from "./utils/testutils2";

chai.use(chaiAsPromised);
chai.use(chaiExclude);
Expand Down Expand Up @@ -60,6 +61,83 @@ const newManagementEntity2 = EntityNames.MANAGEMENT_NEW_ENTITY_2;
type AccessRights = ("Manage" | "Send" | "Listen")[];
const randomDate = new Date();

/**
* These tests are just a sanity check that our updates are actually
* _doing_ something. We've run into some bugs where we've done things like
* enabled forwarding only to find that forwarding isn't happening even though
* we can _read_ the attributes back.
*/
describe("Atom management - forwarding", () => {
let serviceBusClient: ServiceBusClientForTests;

before(() => {
serviceBusClient = createServiceBusClientForTests();
});

after(() => serviceBusClient.test.after());

afterEach(async () => {
serviceBusClient.test.afterEach();
});

it("queue: forwarding", async () => {
const willForward = await serviceBusClient.test.createTestEntities(
TestClientType.PartitionedQueue
);
const willBeForwardedTo = await serviceBusClient.test.createTestEntities(
TestClientType.UnpartitionedQueue
);

// make it so all messages from `willForward` are forwarded to `willBeForwardedTo`
const queueProperties = await serviceBusAtomManagementClient.getQueue(willForward.queue!);
queueProperties.forwardTo = willBeForwardedTo.queue!;
await serviceBusAtomManagementClient.updateQueue(queueProperties);

const receiver = await serviceBusClient.test.createReceiveAndDeleteReceiver(willBeForwardedTo);
const sender = await serviceBusClient.test.createSender(willForward);

await sender.sendMessages({
body: "forwarded message with queues!"
});

const messages = await receiver.receiveMessages(1);
assert.deepEqual(
[{ body: "forwarded message with queues!" }],
messages.map((m) => ({ body: m.body }))
);
});

it("subscription: forwarding", async () => {
const willForward = await serviceBusClient.test.createTestEntities(
TestClientType.PartitionedSubscription
);
const willBeForwardedTo = await serviceBusClient.test.createTestEntities(
TestClientType.UnpartitionedQueue
);

// make it so all messages from `willForward` are forwarded to `willBeForwardedTo`
const subscriptionProperties = await serviceBusAtomManagementClient.getSubscription(
willForward.topic!,
willForward.subscription!
);
subscriptionProperties.forwardTo = willBeForwardedTo.queue!;
await serviceBusAtomManagementClient.updateSubscription(subscriptionProperties);

const receiver = await serviceBusClient.test.createReceiveAndDeleteReceiver(willBeForwardedTo);
const sender = await serviceBusClient.test.createSender(willForward);

await sender.sendMessages({
body: "forwarded message with subscriptions!"
});

const messages = await receiver.receiveMessages(1);
assert.deepEqual(
[{ body: "forwarded message with subscriptions!" }],
messages.map((m) => ({ body: m.body }))
);
});
});

describe("Atom management - Namespace", function(): void {
it("Get namespace properties", async () => {
const namespaceProperties = await serviceBusAtomManagementClient.getNamespaceProperties();
Expand Down