Skip to content

Commit e31eb3e

Browse files
[service-bus] Temporarily disable AMQP body type encoding support for 7.0.6 (Azure#15184)
Disable amqp body type support until we release it in an official 'beta'. Runtime prevention: - Prevent isAmqpAnnotatedMessage() from ever returning true (disables all AMQP body type related code paths) - Fix error message constants so they feature-switch and don't mention AmqpAnnotatedMessage Compile time prevention: - Remove AmqpAnnotatedMessage from the public facing types (ServiceBusMessageBatch and ServiceBusSender) All tests and internals are intact and tests are enabling the code paths internally so tests are still working properly.
1 parent e5f398d commit e31eb3e

File tree

9 files changed

+208
-39
lines changed

9 files changed

+208
-39
lines changed

sdk/servicebus/service-bus/review/service-bus.api.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ export interface ServiceBusMessageBatch {
400400
// @internal
401401
readonly _messageSpanContexts: SpanContext[];
402402
readonly sizeInBytes: number;
403-
tryAddMessage(message: ServiceBusMessage | AmqpAnnotatedMessage, options?: TryAddOptions): boolean;
403+
tryAddMessage(message: ServiceBusMessage, options?: TryAddOptions): boolean;
404404
}
405405

406406
// @public
@@ -459,7 +459,7 @@ export interface ServiceBusSender {
459459
entityPath: string;
460460
isClosed: boolean;
461461
scheduleMessages(messages: ServiceBusMessage | ServiceBusMessage[], scheduledEnqueueTimeUtc: Date, options?: OperationOptionsBase): Promise<Long[]>;
462-
sendMessages(messages: ServiceBusMessage | ServiceBusMessage[] | ServiceBusMessageBatch | AmqpAnnotatedMessage | AmqpAnnotatedMessage[], options?: OperationOptionsBase): Promise<void>;
462+
sendMessages(messages: ServiceBusMessage | ServiceBusMessage[] | ServiceBusMessageBatch, options?: OperationOptionsBase): Promise<void>;
463463
}
464464

465465
// @public

sdk/servicebus/service-bus/src/sender.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,7 @@ export interface ServiceBusSender {
5151
* @throws `ServiceBusError` if the service returns an error while sending messages to the service.
5252
*/
5353
sendMessages(
54-
messages:
55-
| ServiceBusMessage
56-
| ServiceBusMessage[]
57-
| ServiceBusMessageBatch
58-
| AmqpAnnotatedMessage
59-
| AmqpAnnotatedMessage[],
54+
messages: ServiceBusMessage | ServiceBusMessage[] | ServiceBusMessageBatch,
6055
options?: OperationOptionsBase
6156
): Promise<void>;
6257

sdk/servicebus/service-bus/src/serviceBusMessage.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,11 +620,33 @@ export function isServiceBusMessage(possible: unknown): possible is ServiceBusMe
620620
return isObjectWithProperties(possible, ["body"]);
621621
}
622622

623+
let _featureAmqpBodyTypeEnabled = false;
624+
625+
/**
626+
* Disables preview AMQP body type support.
627+
* @internal
628+
*/
629+
export function getFeatureAmqpBodyTypeEnabled(): boolean {
630+
return _featureAmqpBodyTypeEnabled;
631+
}
632+
633+
/**
634+
* Enables preview AMQP body type support.
635+
* @internal
636+
*/
637+
export function setFeatureAmqpBodyTypeEnabledForTesting(enable: boolean): void {
638+
_featureAmqpBodyTypeEnabled = enable;
639+
}
640+
623641
/**
624642
* @internal
625643
* @ignore
626644
*/
627645
export function isAmqpAnnotatedMessage(possible: unknown): possible is AmqpAnnotatedMessage {
646+
if (!_featureAmqpBodyTypeEnabled) {
647+
return false;
648+
}
649+
628650
return (
629651
isObjectWithProperties(possible, ["body", "bodyType"]) &&
630652
possible.constructor.name !== ServiceBusMessageImpl.name

sdk/servicebus/service-bus/src/serviceBusMessageBatch.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,7 @@ export interface ServiceBusMessageBatch {
7070
* @param message - The message to add to the batch.
7171
* @returns A boolean value indicating if the message has been added to the batch or not.
7272
*/
73-
tryAddMessage(
74-
message: ServiceBusMessage | AmqpAnnotatedMessage,
75-
options?: TryAddOptions
76-
): boolean;
73+
tryAddMessage(message: ServiceBusMessage, options?: TryAddOptions): boolean;
7774

7875
/**
7976
* The AMQP message containing encoded events that were added to the batch.

sdk/servicebus/service-bus/src/util/errors.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { logger, receiverLogger } from "../log";
55
import Long from "long";
66
import { ConnectionContext } from "../connectionContext";
77
import {
8+
getFeatureAmqpBodyTypeEnabled,
89
isAmqpAnnotatedMessage,
910
isServiceBusMessage,
1011
ServiceBusReceivedMessage
@@ -269,9 +270,11 @@ export function throwIfNotValidServiceBusMessage(
269270
}
270271

271272
/** @internal */
272-
export const errorInvalidMessageTypeSingleOrArray =
273-
"Provided value for 'messages' must be of type: ServiceBusMessage, AmqpAnnotatedMessage, ServiceBusMessageBatch or an array of type ServiceBusMessage or AmqpAnnotatedMessage.";
273+
export const errorInvalidMessageTypeSingleOrArray = getFeatureAmqpBodyTypeEnabled()
274+
? "Provided value for 'messages' must be of type: ServiceBusMessage, AmqpAnnotatedMessage, ServiceBusMessageBatch or an array of type ServiceBusMessage or AmqpAnnotatedMessage."
275+
: "Provided value for 'messages' must be of type: ServiceBusMessage, ServiceBusMessageBatch or an array of type ServiceBusMessage";
274276

275277
/** @internal */
276-
export const errorInvalidMessageTypeSingle =
277-
"Provided value for 'message' must be of type: ServiceBusMessage or AmqpAnnotatedMessage.";
278+
export const errorInvalidMessageTypeSingle = getFeatureAmqpBodyTypeEnabled()
279+
? "Provided value for 'message' must be of type: ServiceBusMessage or AmqpAnnotatedMessage."
280+
: "Provided value for 'message' must be of type: ServiceBusMessage";

sdk/servicebus/service-bus/test/internal/amqp.spec.ts

Lines changed: 109 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
// Licensed under the MIT license.
33

44
import * as chai from "chai";
5-
import { ServiceBusReceiver, ServiceBusSender } from "../../src";
6-
import {
7-
createServiceBusClientForTests,
8-
ServiceBusClientForTests
9-
} from "../public/utils/testutils2";
5+
import { ServiceBusSender } from "../../src";
106
import { TestClientType } from "../public/utils/testUtils";
7+
import { ServiceBusSenderImpl } from "../../src/sender";
8+
import {
9+
getFeatureAmqpBodyTypeEnabled,
10+
setFeatureAmqpBodyTypeEnabledForTesting
11+
} from "../../src/serviceBusMessage";
12+
import { addServiceBusClientForLiveTesting } from "../public/utils/testutils2";
1113
const assert = chai.assert;
1214

1315
describe("AMQP message encoding", () => {
@@ -16,35 +18,89 @@ describe("AMQP message encoding", () => {
1618

1719
// Primitive types
1820
// http://docs.oasis-open.org/amqp/core/v1.0/csprd01/amqp-core-types-v1.0-csprd01.html#toc
21+
const { sender: _senderImpl, receiver } = addServiceBusClientForLiveTesting(
22+
TestClientType.UnpartitionedQueue
23+
);
24+
const sender: () => Omit<ServiceBusSender, "sendMessages"> &
25+
Pick<ServiceBusSenderImpl, "sendMessages"> = () => {
26+
return _senderImpl();
27+
};
28+
29+
// NOTE: Will remove this entire test suiteonce we re-enable AMQP body type encoding.
30+
describe("AMQP message encoding is disabled", () => {
31+
([
32+
["sequence", [1, 2, 3]],
33+
["value", "hello"],
34+
["data", "hello"]
35+
] as ["sequence" | "data" | "value", any][]).forEach(([originalBodyType, expectedBody]) => {
36+
it("receive ServiceBusMessage and resend", async () => {
37+
await (sender() as ServiceBusSender).sendMessages({
38+
body: expectedBody,
39+
// @ts-expect-error "`bodyType` is not a field in ServiceBusMessage. When AMQP body type encoding is disabled it won't compile"
40+
bodyType: originalBodyType
41+
});
1942

20-
describe("amqp encoding/decoding", () => {
21-
let client: ServiceBusClientForTests;
22-
let sender: ServiceBusSender;
23-
let receiver: ServiceBusReceiver;
43+
const messages = await receiver().receiveMessages(1);
44+
const message = messages[0];
2445

25-
before(() => {
26-
client = createServiceBusClientForTests();
46+
assert.equal(
47+
message._rawAmqpMessage.bodyType,
48+
"data",
49+
"Body type (when AMQP body type encoding is disabled) is always 'data'"
50+
);
51+
52+
// now let's just resend it, unaltered
53+
await sender().sendMessages(message);
54+
55+
const reencodedMessages = await receiver().receiveMessages(1);
56+
const reencodedMessage = reencodedMessages[0];
57+
58+
assert.equal(reencodedMessage._rawAmqpMessage.bodyType, "data");
59+
assert.deepEqual(reencodedMessage.body, expectedBody);
60+
});
2761
});
2862

29-
beforeEach(async () => {
30-
const testEntities = await client.test.createTestEntities(TestClientType.UnpartitionedQueue);
31-
sender = await client.test.createSender(testEntities);
32-
receiver = await client.test.createReceiveAndDeleteReceiver(testEntities);
63+
it("ServiceBusMessageBatch.tryAdd()", async () => {
64+
const batch = await sender().createMessageBatch();
65+
66+
assert.isTrue(
67+
batch.tryAddMessage({
68+
body: "hello",
69+
// @ts-expect-error "`bodyType` is not a field in ServiceBusMessage. When AMQP body type encoding is disabled it won't compile"
70+
bodyType: "value"
71+
})
72+
);
73+
74+
await sender().sendMessages(batch);
75+
76+
const reencodedMessages = await receiver().receiveMessages(1);
77+
const reencodedMessage = reencodedMessages[0];
78+
79+
assert.equal(reencodedMessage._rawAmqpMessage.bodyType, "data");
80+
assert.equal(reencodedMessage.body, "hello");
3381
});
82+
});
3483

35-
afterEach(() => client.test.afterEach());
36-
after(() => client.test.after());
84+
describe("amqp encoding/decoding", () => {
85+
beforeEach(() => {
86+
const previousState = getFeatureAmqpBodyTypeEnabled();
87+
assert.isFalse(previousState);
88+
setFeatureAmqpBodyTypeEnabledForTesting(true);
89+
});
90+
afterEach(() => {
91+
setFeatureAmqpBodyTypeEnabledForTesting(false);
92+
});
3793

3894
it("values", async () => {
3995
const valueTypes = [[1, 2, 3], 1, 1.5, "hello", { hello: "world" }];
4096

4197
for (const valueType of valueTypes) {
42-
await sender.sendMessages({
98+
await sender().sendMessages({
4399
body: valueType,
44100
bodyType: "value"
45101
});
46102

47-
const messages = await receiver.receiveMessages(1);
103+
const messages = await receiver().receiveMessages(1);
48104
const message = messages[0];
49105

50106
assert.deepEqual(
@@ -67,12 +123,12 @@ describe("AMQP message encoding", () => {
67123
];
68124

69125
for (const sequenceType of sequenceTypes) {
70-
await sender.sendMessages({
126+
await sender().sendMessages({
71127
body: sequenceType,
72128
bodyType: "sequence"
73129
});
74130

75-
const messages = await receiver.receiveMessages(1);
131+
const messages = await receiver().receiveMessages(1);
76132
const message = messages[0];
77133

78134
assert.deepEqual(
@@ -94,12 +150,12 @@ describe("AMQP message encoding", () => {
94150
const dataTypes = [1, 1.5, "hello", { hello: "world" }, buff, [1, 2, 3]];
95151

96152
for (const dataType of dataTypes) {
97-
await sender.sendMessages({
153+
await sender().sendMessages({
98154
body: dataType,
99155
bodyType: "data"
100156
});
101157

102-
const messages = await receiver.receiveMessages(1);
158+
const messages = await receiver().receiveMessages(1);
103159
const message = messages[0];
104160

105161
assert.deepEqual(
@@ -114,5 +170,35 @@ describe("AMQP message encoding", () => {
114170
);
115171
}
116172
});
173+
174+
([
175+
["sequence", [1, 2, 3]],
176+
["value", "hello"],
177+
["data", "hello"]
178+
] as ["sequence" | "data" | "value", any][]).forEach(([expectedBodyType, expectedBody]) => {
179+
it("receive ServiceBusMessage and resend", async () => {
180+
// if we receive a message that was encoded to a non-data section
181+
// and then re-send it (again, as a ServiceBusMessage) we should
182+
// respect it.
183+
await sender().sendMessages({
184+
body: expectedBody,
185+
bodyType: expectedBodyType
186+
});
187+
188+
const messages = await receiver().receiveMessages(1);
189+
const message = messages[0];
190+
191+
assert.equal(message._rawAmqpMessage.bodyType, expectedBodyType);
192+
193+
// now let's just resend it, unaltered
194+
await sender().sendMessages(message);
195+
196+
const reencodedMessages = await receiver().receiveMessages(1);
197+
const reencodedMessage = reencodedMessages[0];
198+
199+
assert.equal(reencodedMessage._rawAmqpMessage.bodyType, expectedBodyType);
200+
assert.deepEqual(reencodedMessage.body, expectedBody);
201+
});
202+
});
117203
});
118204
});

sdk/servicebus/service-bus/test/internal/unit/amqpUnitTests.spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
// Licensed under the MIT license.
33

44
import {
5+
getFeatureAmqpBodyTypeEnabled,
56
isAmqpAnnotatedMessage,
67
isServiceBusMessage,
78
ServiceBusMessage,
89
ServiceBusMessageImpl,
910
ServiceBusReceivedMessage,
11+
setFeatureAmqpBodyTypeEnabledForTesting,
1012
toRheaMessage
1113
} from "../../../src/serviceBusMessage";
1214
import * as chai from "chai";
@@ -18,9 +20,33 @@ import {
1820
isRheaAmqpSection,
1921
valueSectionTypeCode
2022
} from "../../../src/dataTransformer";
23+
import {
24+
errorInvalidMessageTypeSingle,
25+
errorInvalidMessageTypeSingleOrArray
26+
} from "../../../src/util/errors";
2127
const assert = chai.assert;
2228

2329
describe("AMQP message encoding", () => {
30+
beforeEach(() => {
31+
assert.equal(
32+
"Provided value for 'messages' must be of type: ServiceBusMessage, ServiceBusMessageBatch or an array of type ServiceBusMessage",
33+
errorInvalidMessageTypeSingleOrArray
34+
);
35+
36+
assert.equal(
37+
"Provided value for 'message' must be of type: ServiceBusMessage",
38+
errorInvalidMessageTypeSingle
39+
);
40+
41+
const previousState = getFeatureAmqpBodyTypeEnabled();
42+
assert.isFalse(previousState);
43+
44+
setFeatureAmqpBodyTypeEnabledForTesting(true);
45+
});
46+
afterEach(() => {
47+
setFeatureAmqpBodyTypeEnabledForTesting(false);
48+
});
49+
2450
const exampleReceivedMessage: () => ServiceBusReceivedMessage = () =>
2551
new ServiceBusMessageImpl(
2652
({

sdk/servicebus/service-bus/test/public/amqpAnnotatedMessage.spec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ import {
1414
} from "../public/utils/testutils2";
1515
import { AmqpAnnotatedMessage } from "@azure/core-amqp";
1616
import { generateUuid } from "@azure/core-http";
17+
import {
18+
getFeatureAmqpBodyTypeEnabled,
19+
setFeatureAmqpBodyTypeEnabledForTesting
20+
} from "../../src/serviceBusMessage";
1721

1822
const should = chai.should();
1923
chai.use(chaiAsPromised);
@@ -67,10 +71,15 @@ function getSampleAmqpAnnotatedMessage(randomTag?: string): AmqpAnnotatedMessage
6771

6872
describe("AmqpAnnotatedMessage", function(): void {
6973
before(() => {
74+
const previousState = getFeatureAmqpBodyTypeEnabled();
75+
assert.isFalse(previousState);
76+
77+
setFeatureAmqpBodyTypeEnabledForTesting(true);
7078
serviceBusClient = createServiceBusClientForTests();
7179
});
7280

7381
after(() => {
82+
setFeatureAmqpBodyTypeEnabledForTesting(false);
7483
return serviceBusClient.test.after();
7584
});
7685

0 commit comments

Comments
 (0)