-
Notifications
You must be signed in to change notification settings - Fork 462
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
EdgeHub: Add support for a RetryingClient to handle SDK issues (#1239) (
#1255) * EdgeHub: Add support for a RetryingClient to handle SDK issues (#1239) * Add support for retrying CloudProxy * Add Tests * Add / fix tests * Cleanup and fix test * Fix build * Update RetryingCloudProxyTest.cs * Fix build * Fix RetryCount usage * Fix RetryingCloudProxy loop * Update RetryingCloudProxy.cs * remove env var (#1247) (#1253) * Dispose client on getting an Object Disposed exception (#1211) (#1251) * Kill EA on ObjDispException (#1254) * EdgeHub: Add support for a RetryingClient to handle SDK issues (#1239) * Add support for retrying CloudProxy * Add Tests * Add / fix tests * Cleanup and fix test * Fix build * Update RetryingCloudProxyTest.cs * Fix build * Fix RetryCount usage * Fix RetryingCloudProxy loop * Update RetryingCloudProxy.cs * Fix build
- Loading branch information
1 parent
bbc8d3c
commit 7598ef0
Showing
8 changed files
with
607 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/cloud/RetryingCloudProxy.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
namespace Microsoft.Azure.Devices.Edge.Hub.Core.Cloud | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
using Microsoft.Azure.Devices.Edge.Util; | ||
using Nito.AsyncEx; | ||
|
||
public class RetryingCloudProxy : ICloudProxy | ||
{ | ||
const int RetryCount = 3; | ||
readonly AsyncLock cloudProxyLock = new AsyncLock(); | ||
readonly Func<Task<Try<ICloudProxy>>> cloudProxyGetter; | ||
|
||
ICloudProxy innerCloudProxy; | ||
|
||
public RetryingCloudProxy(Func<Task<Try<ICloudProxy>>> cloudProxyGetter, ICloudProxy cloudProxyImplementation) | ||
{ | ||
this.cloudProxyGetter = Preconditions.CheckNotNull(cloudProxyGetter, nameof(cloudProxyGetter)); | ||
this.innerCloudProxy = Preconditions.CheckNotNull(cloudProxyImplementation, nameof(cloudProxyImplementation)); | ||
} | ||
|
||
public bool IsActive => this.innerCloudProxy.IsActive; | ||
|
||
internal ICloudProxy InnerCloudProxy => this.innerCloudProxy; | ||
|
||
public Task<bool> CloseAsync() => this.ExecuteOperation(c => c.CloseAsync()); | ||
|
||
public Task<bool> OpenAsync() => this.ExecuteOperation(c => c.OpenAsync()); | ||
|
||
public Task SendMessageAsync(IMessage message) => this.ExecuteOperation(c => c.SendMessageAsync(message)); | ||
|
||
public Task SendMessageBatchAsync(IEnumerable<IMessage> inputMessages) => this.ExecuteOperation(c => c.SendMessageBatchAsync(inputMessages)); | ||
|
||
public Task UpdateReportedPropertiesAsync(IMessage reportedPropertiesMessage) => this.ExecuteOperation(c => c.UpdateReportedPropertiesAsync(reportedPropertiesMessage)); | ||
|
||
public Task<IMessage> GetTwinAsync() => this.ExecuteOperation(c => c.GetTwinAsync()); | ||
|
||
public Task SendFeedbackMessageAsync(string messageId, FeedbackStatus feedbackStatus) => this.ExecuteOperation(c => c.SendFeedbackMessageAsync(messageId, feedbackStatus)); | ||
|
||
public Task SetupCallMethodAsync() => this.ExecuteOperation(c => c.SetupCallMethodAsync()); | ||
|
||
public Task RemoveCallMethodAsync() => this.ExecuteOperation(c => c.RemoveCallMethodAsync()); | ||
|
||
public Task SetupDesiredPropertyUpdatesAsync() => this.ExecuteOperation(c => c.SetupDesiredPropertyUpdatesAsync()); | ||
|
||
public Task RemoveDesiredPropertyUpdatesAsync() => this.ExecuteOperation(c => c.RemoveDesiredPropertyUpdatesAsync()); | ||
|
||
public Task StartListening() => this.ExecuteOperation(c => c.StartListening()); | ||
|
||
Task ExecuteOperation(Func<ICloudProxy, Task> func) => this.ExecuteOperation( | ||
async c => | ||
{ | ||
await func(c); | ||
return 1; | ||
}); | ||
|
||
async Task<T> ExecuteOperation<T>(Func<ICloudProxy, Task<T>> func) | ||
{ | ||
int i = 0; | ||
while (true) | ||
{ | ||
ICloudProxy cloudProxy = await this.GetCloudProxy(); | ||
try | ||
{ | ||
return await func(cloudProxy); | ||
} | ||
catch (Exception) | ||
{ | ||
if (cloudProxy.IsActive || ++i == RetryCount) | ||
{ | ||
throw; | ||
} | ||
} | ||
} | ||
} | ||
|
||
async Task<ICloudProxy> GetCloudProxy() | ||
{ | ||
if (!this.innerCloudProxy.IsActive) | ||
{ | ||
using (await this.cloudProxyLock.LockAsync()) | ||
{ | ||
if (!this.innerCloudProxy.IsActive) | ||
{ | ||
Try<ICloudProxy> cloudProxyTry = await this.cloudProxyGetter(); | ||
if (!cloudProxyTry.Success) | ||
{ | ||
throw new EdgeHubIOException("Unable to create IoTHub connection", cloudProxyTry.Exception); | ||
} | ||
|
||
this.innerCloudProxy = cloudProxyTry.Value; | ||
} | ||
} | ||
} | ||
|
||
return this.innerCloudProxy; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.