Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/previews/mockclients' into vinag…
Browse files Browse the repository at this point in the history
…esh/mocktomaster
  • Loading branch information
vinagesh committed Jul 21, 2021
2 parents 762db48 + af7b805 commit 6e6af9f
Show file tree
Hide file tree
Showing 13 changed files with 2,978 additions and 3,297 deletions.
419 changes: 0 additions & 419 deletions iothub/service/src/AmqpServiceClient.cs

This file was deleted.

122 changes: 65 additions & 57 deletions iothub/service/src/DigitalTwin/DigitalTwinClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,60 +27,12 @@ public class DigitalTwinClient : IDisposable
private readonly IotHubGatewayServiceAPIs _client;
private readonly PnpDigitalTwin _protocolLayer;

private DigitalTwinClient(string hostName, DigitalTwinServiceClientCredentials credentials, params DelegatingHandler[] handlers)
{
var httpsEndpoint = new UriBuilder(HttpsEndpointPrefix, hostName).Uri;
var httpMessageHandler = HttpClientHelper.CreateDefaultHttpMessageHandler(null, httpsEndpoint, ServicePointHelpers.DefaultConnectionLeaseTimeout);
#pragma warning disable CA2000 // Dispose objects before losing scope (httpMessageHandlerWithDelegatingHandlers is disposed when the http client owning it is disposed)
HttpMessageHandler httpMessageHandlerWithDelegatingHandlers = CreateHttpHandlerPipeline(httpMessageHandler, handlers);
#pragma warning restore CA2000 // Dispose objects before losing scope

#pragma warning disable CA2000 // Dispose objects before losing scope (httpClient is disposed when the protocol layer client owning it is disposed)
var httpClient = new HttpClient(httpMessageHandlerWithDelegatingHandlers, true)
{
BaseAddress = httpsEndpoint
};
#pragma warning restore CA2000 // Dispose objects before losing scope

#pragma warning restore CA2000 // Dispose objects before losing scope

// When this client is disposed, all the http message handlers and delegating handlers will be disposed automatically
_client = new IotHubGatewayServiceAPIs(credentials, httpClient, true);
_client.BaseUri = httpsEndpoint;
_protocolLayer = new PnpDigitalTwin(_client);
}

// Creates a single HttpMessageHandler to construct a HttpClient with from a base httpMessageHandler and some number of custom delegating handlers
// This is almost a copy of the Microsoft.Rest.ClientRuntime library's implementation, but with the return and parameter type HttpClientHandler replaced
// with the more abstract HttpMessageHandler in order for us to set the base handler as either a SocketsHttpHandler for .net core or an HttpClientHandler otherwise
// https://github.com/Azure/azure-sdk-for-net/blob/99f4da88ab0aa01c79aa291c6c101ab94c4ac940/sdk/mgmtcommon/ClientRuntime/ClientRuntime/ServiceClient.cs#L376
private static HttpMessageHandler CreateHttpHandlerPipeline(HttpMessageHandler httpMessageHandler, params DelegatingHandler[] handlers)
/// <summary>
/// Creates an instance of <see cref="DigitalTwinClient"/>, provided for unit testing purposes only.
/// Use the CreateFromConnectionString or Create method to create an instance to use the client.
/// </summary>
public DigitalTwinClient()
{
// The RetryAfterDelegatingHandler should be the absolute outermost handler
// because it's extremely lightweight and non-interfering
HttpMessageHandler currentHandler =
#pragma warning disable CA2000 // Dispose objects before losing scope (delegating handler is disposed when the http client that uses it is disposed)
new RetryDelegatingHandler(new RetryAfterDelegatingHandler { InnerHandler = httpMessageHandler });
#pragma warning restore CA2000 // Dispose objects before losing scope

if (handlers != null)
{
for (int i = handlers.Length - 1; i >= 0; --i)
{
DelegatingHandler handler = handlers[i];
// Non-delegating handlers are ignored since we always
// have RetryDelegatingHandler as the outer-most handler
while (handler.InnerHandler is DelegatingHandler)
{
handler = handler.InnerHandler as DelegatingHandler;
}

handler.InnerHandler = currentHandler;
currentHandler = handlers[i];
}
}

return currentHandler;
}

/// <summary>
Expand Down Expand Up @@ -157,7 +109,7 @@ public static DigitalTwinClient Create(
/// <param name="digitalTwinId">The Id of the digital twin.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The application/json digital twin and the http response.</returns>
public async Task<HttpOperationResponse<T, DigitalTwinGetHeaders>> GetDigitalTwinAsync<T>(string digitalTwinId, CancellationToken cancellationToken = default)
public virtual async Task<HttpOperationResponse<T, DigitalTwinGetHeaders>> GetDigitalTwinAsync<T>(string digitalTwinId, CancellationToken cancellationToken = default)
{
using HttpOperationResponse<string, DigitalTwinGetHeaders> response = await _protocolLayer.GetDigitalTwinWithHttpMessagesAsync(digitalTwinId, null, cancellationToken)
.ConfigureAwait(false);
Expand All @@ -179,7 +131,7 @@ public async Task<HttpOperationResponse<T, DigitalTwinGetHeaders>> GetDigitalTwi
/// <param name="requestOptions">The optional settings for this request.</param>
/// <param name="cancellationToken">The cancellationToken.</param>
/// <returns>The http response.</returns>
public Task<HttpOperationHeaderResponse<DigitalTwinUpdateHeaders>> UpdateDigitalTwinAsync(
public virtual Task<HttpOperationHeaderResponse<DigitalTwinUpdateHeaders>> UpdateDigitalTwinAsync(
string digitalTwinId,
string digitalTwinUpdateOperations,
DigitalTwinUpdateRequestOptions requestOptions = default,
Expand All @@ -197,7 +149,7 @@ public Task<HttpOperationHeaderResponse<DigitalTwinUpdateHeaders>> UpdateDigital
/// <param name="requestOptions">The optional settings for this request.</param>
/// <param name="cancellationToken">The cancellationToken.</param>
/// <returns>The application/json command invocation response and the http response. </returns>
public async Task<HttpOperationResponse<DigitalTwinCommandResponse, DigitalTwinInvokeCommandHeaders>> InvokeCommandAsync(
public virtual async Task<HttpOperationResponse<DigitalTwinCommandResponse, DigitalTwinInvokeCommandHeaders>> InvokeCommandAsync(
string digitalTwinId,
string commandName,
string payload = default,
Expand Down Expand Up @@ -232,7 +184,7 @@ public async Task<HttpOperationResponse<DigitalTwinCommandResponse, DigitalTwinI
/// <param name="requestOptions">The optional settings for this request.</param>
/// <param name="cancellationToken">The cancellationToken.</param>
/// <returns>The application/json command invocation response and the http response. </returns>
public async Task<HttpOperationResponse<DigitalTwinCommandResponse, DigitalTwinInvokeCommandHeaders>> InvokeComponentCommandAsync(
public virtual async Task<HttpOperationResponse<DigitalTwinCommandResponse, DigitalTwinInvokeCommandHeaders>> InvokeComponentCommandAsync(
string digitalTwinId,
string componentName,
string commandName,
Expand Down Expand Up @@ -274,5 +226,61 @@ protected virtual void Dispose(bool disposing)
{
_client?.Dispose();
}

private DigitalTwinClient(string hostName, DigitalTwinServiceClientCredentials credentials, params DelegatingHandler[] handlers)
{
var httpsEndpoint = new UriBuilder(HttpsEndpointPrefix, hostName).Uri;
var httpMessageHandler = HttpClientHelper.CreateDefaultHttpMessageHandler(null, httpsEndpoint, ServicePointHelpers.DefaultConnectionLeaseTimeout);
#pragma warning disable CA2000 // Dispose objects before losing scope (httpMessageHandlerWithDelegatingHandlers is disposed when the http client owning it is disposed)
HttpMessageHandler httpMessageHandlerWithDelegatingHandlers = CreateHttpHandlerPipeline(httpMessageHandler, handlers);
#pragma warning restore CA2000 // Dispose objects before losing scope

#pragma warning disable CA2000 // Dispose objects before losing scope (httpClient is disposed when the protocol layer client owning it is disposed)
var httpClient = new HttpClient(httpMessageHandlerWithDelegatingHandlers, true)
{
BaseAddress = httpsEndpoint
};
#pragma warning restore CA2000 // Dispose objects before losing scope

#pragma warning restore CA2000 // Dispose objects before losing scope

// When this client is disposed, all the http message handlers and delegating handlers will be disposed automatically
_client = new IotHubGatewayServiceAPIs(credentials, httpClient, true);
_client.BaseUri = httpsEndpoint;
_protocolLayer = new PnpDigitalTwin(_client);
}

// Creates a single HttpMessageHandler to construct a HttpClient with from a base httpMessageHandler and some number of custom delegating handlers
// This is almost a copy of the Microsoft.Rest.ClientRuntime library's implementation, but with the return and parameter type HttpClientHandler replaced
// with the more abstract HttpMessageHandler in order for us to set the base handler as either a SocketsHttpHandler for .net core or an HttpClientHandler otherwise
// https://github.com/Azure/azure-sdk-for-net/blob/99f4da88ab0aa01c79aa291c6c101ab94c4ac940/sdk/mgmtcommon/ClientRuntime/ClientRuntime/ServiceClient.cs#L376
private static HttpMessageHandler CreateHttpHandlerPipeline(HttpMessageHandler httpMessageHandler, params DelegatingHandler[] handlers)
{
// The RetryAfterDelegatingHandler should be the absolute outermost handler
// because it's extremely lightweight and non-interfering
HttpMessageHandler currentHandler =
#pragma warning disable CA2000 // Dispose objects before losing scope (delegating handler is disposed when the http client that uses it is disposed)
new RetryDelegatingHandler(new RetryAfterDelegatingHandler { InnerHandler = httpMessageHandler });
#pragma warning restore CA2000 // Dispose objects before losing scope

if (handlers != null)
{
for (int i = handlers.Length - 1; i >= 0; --i)
{
DelegatingHandler handler = handlers[i];
// Non-delegating handlers are ignored since we always
// have RetryDelegatingHandler as the outer-most handler
while (handler.InnerHandler is DelegatingHandler)
{
handler = handler.InnerHandler as DelegatingHandler;
}

handler.InnerHandler = currentHandler;
currentHandler = handlers[i];
}
}

return currentHandler;
}
}
}
Loading

0 comments on commit 6e6af9f

Please sign in to comment.