Skip to content

Commit d0b70a8

Browse files
authored
[ServiceBus] expose omitMessagesBody option under ./experimental subpath (#31361)
playing with the idea of exposing features under the `./experimental` subpath and add a dev-tool command to report error if we consume experimental Apis in a GA package. [ServiceBus] Add the experimental diagnostic feature omitMessageBody via an augmented `PeekMessagesOptions` interface under `./experimental` subpath export. After migrating to ESM, we no longer use rolled-up dts files thus lose the ability to trim `@beta` Apis from public type definition files. This PR explores an approach to expose Apis from the `./experimental` export.
1 parent 24d7877 commit d0b70a8

File tree

9 files changed

+133
-18
lines changed

9 files changed

+133
-18
lines changed

sdk/servicebus/service-bus/CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Features Added
66

77
- Adds `deleteMessages` which deletes messages from the queue.
8+
- Add the experimental diagnostic feature `omitMessageBody` via `PeekMessagesOptions` under `./experimental` subpath export.
89

910
### Breaking Changes
1011

@@ -424,8 +425,8 @@ If migrating from version 1.1.10 or lower, look at our [migration guide to move
424425

425426
```typescript
426427
// this same method will work with subscriptions as well.
427-
serviceBusClient.createReceiver(<queue>, {
428-
subQueue: "deadLetter"
428+
serviceBusClient.createReceiver("<queue name>", {
429+
subQueue: "deadLetter",
429430
});
430431
```
431432

sdk/servicebus/service-bus/package.json

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@
143143
"tshy": {
144144
"exports": {
145145
"./package.json": "./package.json",
146-
".": "./src/index.ts"
146+
".": "./src/index.ts",
147+
"./experimental": "./src/experimental/index.ts"
147148
},
148149
"dialects": [
149150
"esm",
@@ -174,6 +175,24 @@
174175
"types": "./dist/commonjs/index.d.ts",
175176
"default": "./dist/commonjs/index.js"
176177
}
178+
},
179+
"./experimental": {
180+
"browser": {
181+
"types": "./dist/browser/experimental/index.d.ts",
182+
"default": "./dist/browser/experimental/index.js"
183+
},
184+
"react-native": {
185+
"types": "./dist/react-native/experimental/index.d.ts",
186+
"default": "./dist/react-native/experimental/index.js"
187+
},
188+
"import": {
189+
"types": "./dist/esm/experimental/index.d.ts",
190+
"default": "./dist/esm/experimental/index.js"
191+
},
192+
"require": {
193+
"types": "./dist/commonjs/experimental/index.d.ts",
194+
"default": "./dist/commonjs/experimental/index.js"
195+
}
177196
}
178197
}
179198
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## API Report File for "@azure/service-bus"
2+
3+
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
4+
5+
```ts
6+
7+
// (No @packageDocumentation comment for this package)
8+
9+
```

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,6 @@ export function parseServiceBusConnectionString(connectionString: string): Servi
211211
// @public
212212
export interface PeekMessagesOptions extends OperationOptionsBase {
213213
fromSequenceNumber?: Long;
214-
// @beta
215-
omitMessageBody?: boolean;
216214
}
217215

218216
// @public
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
declare module "../models.js" {
5+
interface PeekMessagesOptions {
6+
/**
7+
* (Experimental for diagnostic purpose) Specifies whether to omit the body when peeking messages. Default value `false`.
8+
*/
9+
omitMessageBody?: boolean;
10+
}
11+
}

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,11 +320,6 @@ export interface PeekMessagesOptions extends OperationOptionsBase {
320320
* The sequence number to start peeking messages from (inclusive).
321321
*/
322322
fromSequenceNumber?: Long;
323-
/**
324-
* @beta
325-
* (Experimental for diagnostic purpose) Specifies whether to omit the body when peeking messages. Default value `false`.
326-
*/
327-
omitMessageBody?: boolean;
328323
}
329324

330325
/**

sdk/servicebus/service-bus/src/receivers/receiver.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -547,21 +547,25 @@ export class ServiceBusReceiverImpl implements ServiceBusReceiver {
547547
skipParsingBodyAsJson: this.skipParsingBodyAsJson,
548548
skipConvertingDate: this.skipConvertingDate,
549549
};
550+
// omitMessageBody is available at runtime, but only exported in experimental subpath
551+
const { fromSequenceNumber, omitMessageBody } = options as PeekMessagesOptions & {
552+
omitMessageBody: boolean;
553+
};
550554
const peekOperationPromise = async (): Promise<ServiceBusReceivedMessage[]> => {
551-
if (options.fromSequenceNumber !== undefined) {
555+
if (fromSequenceNumber !== undefined) {
552556
return this._context
553557
.getManagementClient(this.entityPath)
554558
.peekBySequenceNumber(
555-
options.fromSequenceNumber,
559+
fromSequenceNumber,
556560
maxMessageCount,
557561
undefined,
558-
options.omitMessageBody,
562+
omitMessageBody,
559563
managementRequestOptions,
560564
);
561565
} else {
562566
return this._context
563567
.getManagementClient(this.entityPath)
564-
.peek(maxMessageCount, options.omitMessageBody, managementRequestOptions);
568+
.peek(maxMessageCount, omitMessageBody, managementRequestOptions);
565569
}
566570
};
567571

sdk/servicebus/service-bus/src/receivers/sessionReceiver.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,15 +337,19 @@ export class ServiceBusSessionReceiverImpl implements ServiceBusSessionReceiver
337337
skipParsingBodyAsJson: this._skipParsingBodyAsJson,
338338
skipConvertingDate: this._skipConvertingDate,
339339
};
340+
// omitMessageBody is available at runtime, but only exported in experimental subpath
341+
const { fromSequenceNumber, omitMessageBody } = options as PeekMessagesOptions & {
342+
omitMessageBody: boolean;
343+
};
340344
const peekOperationPromise = async (): Promise<ServiceBusReceivedMessage[]> => {
341-
if (options.fromSequenceNumber !== undefined) {
345+
if (fromSequenceNumber !== undefined) {
342346
return this._context
343347
.getManagementClient(this.entityPath)
344348
.peekBySequenceNumber(
345-
options.fromSequenceNumber,
349+
fromSequenceNumber,
346350
maxMessageCount,
347351
this.sessionId,
348-
options.omitMessageBody,
352+
omitMessageBody,
349353
managementRequestOptions,
350354
);
351355
} else {
@@ -354,7 +358,7 @@ export class ServiceBusSessionReceiverImpl implements ServiceBusSessionReceiver
354358
.peekMessagesBySession(
355359
this.sessionId,
356360
maxMessageCount,
357-
options.omitMessageBody,
361+
omitMessageBody,
358362
managementRequestOptions,
359363
);
360364
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
import { ServiceBusReceiver, ServiceBusSender } from "../../src/index.js";
5+
import {
6+
createServiceBusClientForTests,
7+
EntityName,
8+
ServiceBusClientForTests,
9+
} from "./utils/testutils2.js";
10+
import { TestClientType, TestMessage } from "./utils/testUtils.js";
11+
import { expect } from "./utils/chai.js";
12+
import { afterAll, afterEach, beforeAll, describe, it } from "vitest";
13+
14+
let serviceBusClient: ServiceBusClientForTests;
15+
let entityNames: EntityName;
16+
let sender: ServiceBusSender;
17+
let receiveAndDeleteReceiver: ServiceBusReceiver;
18+
19+
async function beforeEachTest(entityType: TestClientType): Promise<void> {
20+
entityNames = await serviceBusClient.test.createTestEntities(entityType);
21+
receiveAndDeleteReceiver =
22+
await serviceBusClient.test.createReceiveAndDeleteReceiver(entityNames);
23+
24+
sender = serviceBusClient.test.addToCleanup(
25+
serviceBusClient.createSender(entityNames.queue ?? entityNames.topic!),
26+
);
27+
}
28+
29+
function afterEachTest(): Promise<void> {
30+
return serviceBusClient.test.afterEach();
31+
}
32+
describe("PeekMessagesOptions.omitMessageBody", () => {
33+
beforeAll(() => {
34+
serviceBusClient = createServiceBusClientForTests();
35+
});
36+
37+
afterAll(() => {
38+
return serviceBusClient.test.after();
39+
});
40+
41+
afterEach(async () => {
42+
await afterEachTest();
43+
});
44+
45+
[
46+
TestClientType.UnpartitionedQueue,
47+
TestClientType.UnpartitionedSubscription,
48+
// Service issue feature doesn't work for PartitionedQueue and PartitionedSubscription
49+
// TestClientType.PartitionedQueue,
50+
// TestClientType.PartitionedSubscription,
51+
TestClientType.UnpartitionedQueueWithSessions,
52+
TestClientType.UnpartitionedSubscriptionWithSessions,
53+
TestClientType.PartitionedQueueWithSessions,
54+
TestClientType.PartitionedSubscriptionWithSessions,
55+
].forEach((testType) => {
56+
it(testType + ": peek messages", async () => {
57+
await beforeEachTest(testType);
58+
const testMessages = entityNames.usesSessions
59+
? TestMessage.getSessionSample()
60+
: TestMessage.getSample();
61+
await sender.sendMessages(testMessages);
62+
63+
const peeked = await receiveAndDeleteReceiver.peekMessages(1, {
64+
omitMessageBody: true,
65+
});
66+
67+
expect(peeked.length).to.equal(1);
68+
expect(peeked[0].body).toBeUndefined();
69+
70+
const received = await receiveAndDeleteReceiver.receiveMessages(1);
71+
expect(received.length).toBe(1);
72+
});
73+
});
74+
});

0 commit comments

Comments
 (0)