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] Update constructors to add overloads and use Azure Identity #5436

Merged
merged 25 commits into from
Jan 15, 2020
Merged
Show file tree
Hide file tree
Changes from 17 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
6 changes: 3 additions & 3 deletions sdk/servicebus/service-bus/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ module.exports = function(config) {
// https://www.npmjs.com/package/karma-env-preprocessor
envPreprocessor: [
"SERVICEBUS_CONNECTION_STRING_BROWSER",
"AAD_CLIENT_ID",
"AAD_CLIENT_SECRET",
"AAD_TENANT_ID"
"AZURE_CLIENT_ID",
"AZURE_CLIENT_SECRET",
"AZURE_TENANT_ID"
],

// test results reporter to use
Expand Down
5 changes: 3 additions & 2 deletions sdk/servicebus/service-bus/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@
]
},
"dependencies": {
"@azure/core-amqp": "1.0.0-preview.3",
Copy link
Contributor

@ramya-rao-a ramya-rao-a Jan 10, 2020

Choose a reason for hiding this comment

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

Change to use latest of core-amqp and fixing MessagingError as a consequence is being done as part of #6861
Any reason to include these changes in this PR?

Copy link
Member Author

@ramya0820 ramya0820 Jan 13, 2020

Choose a reason for hiding this comment

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

No reason, ideally that should have been merged already - branch will get updated once that's done

EDIT: I think this was necessary for build to pass based on version used in event hubs

Copy link
Contributor

Choose a reason for hiding this comment

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

Feel free to use the allowedAlternativeVersions section in the common-versions.json file to get rush to allow you to use different versions of @azure/core-amqp in Service Bus vs Event Hubs.

This PR is for the Azure identity work and it would help if the changes here are restricted to using the @azure/identity library in the constructors.

If #6861 gets merged before this PR, we can then

  • rebase your branch from feature/service-bus-track-2
  • revert the change to common-versions.json file

Copy link
Member Author

Choose a reason for hiding this comment

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

I looked over the diffs - the duplicate changes related to core-amqp are very few and can be ignored - it's this one line change updating version, and the type casting ones in files messageReceiver.ts, messageSender.ts and batchingReceiver.ts. (You can ignore the files altogether if they already appear in #6861)

All other 24-25 files are relevant and can be reviewed. The build succeeds as well.

"@azure/core-amqp": "^1.0.0",
"@azure/core-http": "^1.0.0",
"@azure/ms-rest-nodeauth": "^0.9.2",
"@azure/identity": "^1.0.0",
"@opentelemetry/types": "^0.2.0",
"@types/is-buffer": "^2.0.0",
"@types/long": "^4.0.0",
Expand All @@ -93,6 +93,7 @@
},
"devDependencies": {
"@azure/eslint-plugin-azure-sdk": "^2.0.1",
"@azure/ms-rest-nodeauth": "^0.9.2",
Copy link
Contributor

Choose a reason for hiding this comment

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

Now that aadutils.ts file is deleted, we don't need @azure/ms-rest-nodeauth in tests either right?

Copy link
Member Author

Choose a reason for hiding this comment

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

agree, updated

"@microsoft/api-extractor": "^7.5.4",
"@rollup/plugin-json": "^4.0.0",
"@rollup/plugin-multi-entry": "^3.0.0",
Expand Down
3 changes: 2 additions & 1 deletion sdk/servicebus/service-bus/review/service-bus.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,9 @@ export interface ServiceBusAtomManagementClientOptions {

// @public
export class ServiceBusClient {
constructor(connectionString: string, options?: ServiceBusClientOptions);
constructor(credential: TokenCredential, host: string, options?: ServiceBusClientOptions);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the ordering of parameters here should be switched for consistency with event hubs.

constructor(host: string, credential: TokenCredential, options?: ServiceBusClientOptions);

This also matches the sample in the typescript design guidelines.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, could you point to which guideline is being considered for this?

Because I found the following that seems similar / applicable for hostOrConnectionString usage

// bad example
class ExampleClient {
  constructor (connectionString: string, options: ExampleClientOptions);
  constructor (url: string, options: ExampleClientOptions);
  constructor (urlOrCS: string, options: ExampleClientOptions) {
    // have to dig into the first parameter to see whether its
    // a url or a connection string. Not ideal.
  }
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Link was hidden in the word 'guidelines' :)
https://azure.github.io/azure-sdk/typescript_design.html#ts-apisurface-serviceclient

See the Client API example.

// client constructors have overloads for handling different
// authentication schemes.
constructor(connectionString: string, options?: ServiceClientOptions);
constructor(host: string, credential: TokenCredential, options?: ServiceClientOptions);

Copy link
Contributor

Choose a reason for hiding this comment

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

The reason the example you posted is considered bad is because the type signatures for both constructors are exactly the same (string, options). In our case though we have 2 unique signatures (string, options) and (string, TokenCredential, options)

Copy link
Member Author

Choose a reason for hiding this comment

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

Unable to reply to other comment for some reason :?
Yes, EventHubs impl seems to have the different concerns addressed. The type of error being thrown is useful to note as well (TypeError as opposed to simple Error)
I just have the guideline aspect clarification pending - ok to be consistent with EventHubs if that's what we want to do
Thoughts? @ramya-rao-a @bterlson

Personally, I think the example called out on the guidelines page resonates with my initial thoughts on switching the parameters - also because credential based constructor sounded more right too, than host based. (Going by the first parameter to pass in).

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, the other observation I had was that options parameter being optional - seemed out of place to rely on type of to decide which constructor to use at first. So without that it can come down to two parameter constructor :?

Like, JS in general isn't strict on parameter numbers to be passed in.
So I think the one usecase that I had brought up earlier and seems to not be handled by EventHubs is if user invokes the host and credential based constructor as
(hostName, undefined, options) - then it looks like the error user would get would be about having to pass in a correctly formatted connection string.

Copy link
Member Author

Choose a reason for hiding this comment

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

To summarize the thread here - the user experience for when credential is passed in as undefined is the one that seems unaddressed.

Let's take a call on if we want to address that as a bug and fix it here or not - and if we want to still go ahead with mirroring EventHubs constructors for most part.

cc @ramya-rao-a @chradek
@bterlson @AlexGhiondea

Copy link
Contributor

Choose a reason for hiding this comment

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

The situation where a user passed undefined for the credential but still passes the options after it seems very unlikely. I think you could make the argument that if they're explicitly trying to not pass in a TokenCredential, then they would want a connection string (so the error seems relevant). But, I don't feel too strongly since they would be going against the types and docs in this case (I'm glad we give some error).

With regards to the parameter order for the constructors, my vote is for consistency. Since event-hubs is already GA, changing the order there would need a major version bump. I see one of our goals as providing a consistent experience across the packages we own (when possible) to lower the learning curve for users going from one package to another.

Copy link
Member Author

@ramya0820 ramya0820 Jan 14, 2020

Choose a reason for hiding this comment

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

Fair point, updated parameters ordering to keep up with consistency as if we decide to change, we can do it together

Agree that explicitly passing in undefined would map more to connection string based constructor.
But if say a user is instantiating the credentials programmatically, they could run into an undefined object.
Event Hubs seems a bit different in that it accepts event hub name in addition to connection string in Event Hubs SDK. So it seems a little more relevant to Event Hubs as the err msg can be confusing to troubleshoot. (Also I wonder how long it might be before we bump version, maybe that would happen at same time as when Track 2 SB would go GA, but I digress :) )

And.. if we are of pinion that this a not so ideal state afterall, then we could have not so ideal string processing to guard against the missing/undefined token credentials case in Service Bus possibly. Let me know. For now haven't included those checks since we didn't want those. @ramya-rao-a Ok if we choose to handle it all together later as well or file a new issue?
Because it seems like we might be regressing from Track 1 if we are no longer able to surface the error we used to be able to - "'credentials' is a required parameter and must be an instance of ...

close(): Promise<any>;
static createFromConnectionString(connectionString: string, options?: ServiceBusClientOptions): ServiceBusClient;
createQueueClient(queueName: string): QueueClient;
createSubscriptionClient(topicName: string, subscriptionName: string): SubscriptionClient;
createTopicClient(topicName: string): TopicClient;
Expand Down
4 changes: 2 additions & 2 deletions sdk/servicebus/service-bus/src/core/batchingReceiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class BatchingReceiver extends MessageReceiver {
const sessionError = context.session && context.session.error;
let error = new MessagingError("An error occurred while receiving messages.");
if (sessionError) {
error = translate(sessionError);
error = translate(sessionError) as MessagingError;
Copy link
Contributor

Choose a reason for hiding this comment

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

This casting is not required. Same for a few lines below.

log.error(
"[%s] 'session_close' event occurred for Receiver '%s' received an error:\n%O",
this._context.namespace.connectionId,
Expand Down Expand Up @@ -263,7 +263,7 @@ export class BatchingReceiver extends MessageReceiver {
const receiverError = context.receiver && context.receiver.error;
let error = new MessagingError("An error occurred while receiving messages.");
if (receiverError) {
error = translate(receiverError);
error = translate(receiverError) as MessagingError;
log.error(
"[%s] Receiver '%s' received an error:\n%O",
this._context.namespace.connectionId,
Expand Down
6 changes: 3 additions & 3 deletions sdk/servicebus/service-bus/src/core/messageReceiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ export class MessageReceiver extends LinkEntity {
const receiver = this._receiver || context.receiver!;
const receiverError = context.receiver && context.receiver.error;
if (receiverError) {
const sbError = translate(receiverError);
const sbError = translate(receiverError) as MessagingError;
log.error(
"[%s] An error occurred for Receiver '%s': %O.",
connectionId,
Expand Down Expand Up @@ -587,7 +587,7 @@ export class MessageReceiver extends LinkEntity {
const receiver = this._receiver || context.receiver!;
const sessionError = context.session && context.session.error;
if (sessionError) {
const sbError = translate(sessionError);
const sbError = translate(sessionError) as MessagingError;
log.error(
"[%s] An error occurred on the session for Receiver '%s': %O.",
connectionId,
Expand Down Expand Up @@ -875,7 +875,7 @@ export class MessageReceiver extends LinkEntity {
// We should attempt to reopen only when the receiver(sdk) did not initiate the close
let shouldReopen = false;
if (receiverError && !wasCloseInitiated) {
const translatedError = translate(receiverError);
const translatedError = translate(receiverError) as MessagingError;
if (translatedError.retryable) {
shouldReopen = true;
log.error(
Expand Down
5 changes: 3 additions & 2 deletions sdk/servicebus/service-bus/src/core/messageSender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ import {
RetryConfig,
RetryOperationType,
Constants,
delay
delay,
MessagingError
} from "@azure/core-amqp";
import {
SendableMessageInfo,
Expand Down Expand Up @@ -496,7 +497,7 @@ export class MessageSender extends LinkEntity {
// We should attempt to reopen only when the sender(sdk) did not initiate the close
let shouldReopen = false;
if (senderError && !wasCloseInitiated) {
const translatedError = translate(senderError);
const translatedError = translate(senderError) as MessagingError;
if (translatedError.retryable) {
shouldReopen = true;
log.error(
Expand Down
167 changes: 66 additions & 101 deletions sdk/servicebus/service-bus/src/serviceBusClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
ConnectionConfig,
DataTransformer,
TokenCredential,
SharedKeyCredential
SharedKeyCredential,
isTokenCredential
} from "@azure/core-amqp";
import { SubscriptionClient } from "./subscriptionClient";

Expand Down Expand Up @@ -56,23 +57,78 @@ export class ServiceBusClient {
*/
private _context: ConnectionContext;

/**
* Creates a ServiceBusClient for the Service Bus Namespace represented in the given connection
* string.
* @param connectionString - Connection string of the form
* 'Endpoint=sb://my-servicebus-namespace.servicebus.windows.net/;SharedAccessKeyName=my-SA-name;SharedAccessKey=my-SA-key'
* @param options Options to control ways to interact with the
* Service Bus Namespace.
* @returns ServiceBusClient
*/
constructor(connectionString: string, options?: ServiceBusClientOptions);

/**
* Instantiates a ServiceBusClient to interact with a Service Bus Namespace.
*
* @constructor
* @param {ConnectionConfig} config - The connection configuration needed to connect to the
* Service Bus Namespace.
* @param {TokenCredential} [tokenCredential] - SharedKeyCredential object or your
* credential that implements the TokenCredential interface.
* @param {ServiceBusClientOptions} - Options to control ways to interact with the Service Bus
* @param credential - credential that implements the TokenCredential interface.
* @param host - The host name for the Service Bus namespace. This is likely to be similar to
* <yournamespace>.servicebus.windows.net
* @param options - Options to control ways to interact with the Service Bus
* Namespace.
*/
private constructor(
config: ConnectionConfig,
credential: SharedKeyCredential | TokenCredential,
constructor(credential: TokenCredential, host: string, options?: ServiceBusClientOptions);

constructor(
connectionStringOrCredential: string | TokenCredential,
hostOrServiceBusClientOptions?: string | ServiceBusClientOptions,
options?: ServiceBusClientOptions
) {
if (!options) options = {};
let config;
let credential;
let connectionString;

if (connectionStringOrCredential == undefined) {
throw new Error("Input parameter 'connectionString' or 'credentials' must be defined.");
}

if (!options) {
options = {};
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The above checks are not needed. ConnectionConfig.create() ensures that String() is called on the given connection string. If the connection string thus stringified doesnt meet the requirements of a connection string, then appropriate errors are thrown from ConnectionConfig.create().

I would suggest the below for handling the overloads

if (!isTokenCredential(credentialOrServiceBusClientOptions)) {
    // assume that first overload is used & create the ConnectionConfig
} else {
    // assume that second overload is used & create the ConnectionConfig
}
// create the connection context

Copy link
Member Author

Choose a reason for hiding this comment

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

The reason for converting to String is because if it's a hostname then we use a .endsWith() check in here

Copy link
Contributor

Choose a reason for hiding this comment

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

You should still be able to use hostOrConnectionString.endsWith(), TS should not complain as the type is already set to string in the constructor signature.

If you want to avoid the case of runtime error for when a bad type is passed, then you can use hostOrConnectionString = String(hostOrConnectionString). Since then endsWith() check is needed only in the case of TokenCredential, you can move this inside the if/else block as well.

Copy link
Member Author

Choose a reason for hiding this comment

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

Any reason why we want to convert it to type String and not use .toString()? If i remember correctly, I think @bterlson had once discussed, advised about not doing so and using string where possible.
And yes, the conversion was to help with both compile and run time scenarios.

Copy link
Contributor

Choose a reason for hiding this comment

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

My intention here is to simplify the logic to handle the constructor overloads.
Currently, we are adding multiple lines of code to ensure that hostOrConnectionString is indeed a string and that it has = in it. We can avoid the need for this and the future tax of maintaining them as well.

For example, when the constructor overload is using connection string, we shouldnt need to do any checks on hostOrConnectionString as that work is offloaded to the downstream ConnectionConfig.create().

When the constructor overload for credential is being used, us using String() will ensure that if user had provided an object with .toString() defined, then it gets called and used correctly. If the passed object does not have .toString() on it, then the connection to the service would fail eventually with the service providing an error message hinting that the provided host name is not valid.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think there's a trade off with quality of expected user experience here possibly - for instance, if a user is passing in the hostname correctly and receives a connection string malformed error, wouldn't that be confusing / inappropriate?

Copy link
Member Author

@ramya0820 ramya0820 Jan 14, 2020

Choose a reason for hiding this comment

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

For above, let's say the inputs are passed along with a malformed / incorrect / unsupported type of credentials.
Current changes address these cases.
Offloading the check to service or core-amqp, which expect a connection string, would make it not possible to do so. (So I'd keep the current changes unless we want or are okay that user receives the connection string related error, in these scenarios - I had added tests reflecting the behavior current changes emulate, can take a look at those. Will need to update those as well, based on what we decide to do.)

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated to use a different signature for the credential based constructor - should likely help with both simplification/maintenance and user ex concerns.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm just catching up here and I might have missed some things as changes have been made.
1st, I remarked on this in the API file but I do think we want to keep connectionString and host as the first parameter in their respective constructors to be consistent with our other SDKs/guidelines.

I think the original comment was about the checks being done on hostOrConnectionString.

if (
      hostOrConnectionString == undefined ||
      hostOrConnectionString.toString == undefined ||
      hostOrConnectionString.toString().trim() == ""
    ) {
      throw new Error(
        "Input parameter of host or connection string must be defined and coercible to string."
      );
    }

I think @ramya-rao-a 's had 2 points:

  1. We can ensure hostOrConnectionString is a string by wrapping it in String: String(hostOrConnectionString)
    Note that this is different from new String(hostOrConnectionString), which is not what you want (and what I think @bterlson would warn to stay away from).
  2. There are other places where hostOrConnectionString is validated so this check isn't needed.

The EventHubClient constructor shows both of these aspects off (only linking to one line here but look at the rest of the function): https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/eventhub/event-hubs/src/impl/eventHubClient.ts#L339

Event Hubs is a bit more complicated since it has 3 overloads instead of 2, so service bus would be even simpler.

I think the Event Hubs constructor would throw helpful errors for the cases that were being checked before, but if there's something being missed let me know!


if (typeof connectionStringOrCredential == "string") {
// connectionString and options based constructor was invoked
connectionString = connectionStringOrCredential;
config = ConnectionConfig.create(connectionString);

options = hostOrServiceBusClientOptions as ServiceBusClientOptions;
config.webSocket = options && options.webSocket;
config.webSocketEndpointPath = "$servicebus/websocket";
config.webSocketConstructorOptions = options && options.webSocketConstructorOptions;

// Since connectionstring was passed, create a SharedKeyCredential
credential = new SharedKeyCredential(config.sharedAccessKeyName, config.sharedAccessKey);

ConnectionConfig.validate(config);
} else {
// credential, host and options based constructor was invoked
if (!isTokenCredential(connectionStringOrCredential)) {
throw new Error(
"'credentials' is a required parameter and must be an implementation of TokenCredential when using host based constructor overload."
);
}
credential = connectionStringOrCredential as TokenCredential;

hostOrServiceBusClientOptions = String(hostOrServiceBusClientOptions);

if (!hostOrServiceBusClientOptions.endsWith("/")) {
hostOrServiceBusClientOptions += "/";
}
connectionString = `Endpoint=sb://${hostOrServiceBusClientOptions};SharedAccessKeyName=defaultKeyName;SharedAccessKey=defaultKeyValue;`;
config = ConnectionConfig.create(connectionString);
}

this.name = config.endpoint;
this._context = ConnectionContext.create(config, credential, options);
}
Expand Down Expand Up @@ -152,95 +208,4 @@ export class ServiceBusClient {
throw errObj;
}
}

/**
* Creates a ServiceBusClient for the Service Bus Namespace represented in the given connection
* string.
* @param {string} connectionString - Connection string of the form
* 'Endpoint=sb://my-servicebus-namespace.servicebus.windows.net/;SharedAccessKeyName=my-SA-name;SharedAccessKey=my-SA-key'
* @param {ServiceBusClientOptions} [options] Options to control ways to interact with the
* Service Bus Namespace.
* @returns {ServiceBusClient}
*/
static createFromConnectionString(
connectionString: string,
options?: ServiceBusClientOptions
): ServiceBusClient {
const config = ConnectionConfig.create(connectionString);

config.webSocket = options && options.webSocket;
config.webSocketEndpointPath = "$servicebus/websocket";
config.webSocketConstructorOptions = options && options.webSocketConstructorOptions;

// Since connectionstring was passed, create a SharedKeyCredential
const credential = new SharedKeyCredential(config.sharedAccessKeyName, config.sharedAccessKey);

ConnectionConfig.validate(config);

return new ServiceBusClient(config, credential, options);
}

// /**
// * Creates a ServiceBusClient for the Service Bus Namespace represented by the given host using
// * the given TokenProvider.
// * @param {string} host - Fully qualified domain name for Servicebus. Most likely,
// * `<yournamespace>.servicebus.windows.net`.
// * @param {TokenProvider} tokenProvider - Your custom implementation of the {@link https://github.com/Azure/amqp-common-js/blob/master/lib/auth/token.ts Token Provider}
// * interface.
// * @param {ServiceBusClientOptions} options - Options to control ways to interact with the
// * Service Bus Namespace.
// * @returns {ServiceBusClient}
// */
// static createFromTokenProvider(
// host: string,
// tokenProvider: TokenProvider,
// options?: ServiceBusClientOptions
// ): ServiceBusClient {
// host = String(host);
// if (!tokenProvider) {
// throw new TypeError('Missing parameter "tokenProvider"');
// }
// if (!host.endsWith("/")) host += "/";
// const connectionString =
// `Endpoint=sb://${host};SharedAccessKeyName=defaultKeyName;` +
// `SharedAccessKey=defaultKeyValue`;
// const config = ConnectionConfig.create(connectionString);

// config.webSocket = options && options.webSocket;
// config.webSocketEndpointPath = "$servicebus/websocket";
// config.webSocketConstructorOptions = options && options.webSocketConstructorOptions;

// ConnectionConfig.validate(config);
// return new ServiceBusClient(config, tokenProvider, options);
// }

// /**
// * Creates a ServiceBusClient for the Service Bus Namespace represented by the given host using
// * the TokenCredentials generated using the `@azure/ms-rest-nodeauth` library.
// * @param {string} host - Fully qualified domain name for ServiceBus.
// * Most likely, {yournamespace}.servicebus.windows.net
// * @param {ServiceClientCredentials} credentials - The Token credentials generated by using the
// * `@azure/ms-rest-nodeauth` library. It can be one of the following:
// * - ApplicationTokenCredentials
// * - UserTokenCredentials
// * - DeviceTokenCredentials
// * - MSITokenCredentials
// * Token audience (or resource in case of MSI based credentials) to use when creating the credentials is https://servicebus.azure.net/
// * @param {ServiceBusClientOptions} options - Options to control ways to interact with the
// * Service Bus Namespace.
// * @returns {ServiceBusClient}
// */
// static createFromAadTokenCredentials(
// host: string,
// credentials:
// | ApplicationTokenCredentials
// | UserTokenCredentials
// | DeviceTokenCredentials
// | MSITokenCredentials,
// options?: ServiceBusClientOptions
// ): ServiceBusClient {
// host = String(host);
// const tokenProvider = new AadTokenProvider(credentials);
// return ServiceBusClient.createFromTokenProvider(host, tokenProvider, options);
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ async function RunTest(
maxConcurrentCalls: number,
messages: number
): Promise<void> {
const ns = ServiceBusClient.createFromConnectionString(connectionString);
const ns = new ServiceBusClient(connectionString);

const client = ns.createQueueClient(entityPath);
const receiver = client.createReceiver(ReceiveMode.receiveAndDelete);
Expand Down
2 changes: 1 addition & 1 deletion sdk/servicebus/service-bus/test/perf/service-bus/send.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ async function RunTest(
maxInflight: number,
messages: number
): Promise<void> {
const ns = ServiceBusClient.createFromConnectionString(connectionString);
const ns = new ServiceBusClient(connectionString);

const client = ns.createQueueClient(entityPath);
const sender = client.createSender();
Expand Down
Loading