-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #141 from stankovski/retry
Added RetryPolicy
- Loading branch information
Showing
52 changed files
with
1,410 additions
and
1,956 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
123 changes: 123 additions & 0 deletions
123
src/Microsoft.Azure.NotificationHubs.DotNetCore.Tests/NamespaceManagerRetryPolicyTests.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,123 @@ | ||
//------------------------------------------------------------ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. See License.txt in the project root for | ||
// license information. | ||
//------------------------------------------------------------ | ||
|
||
namespace Microsoft.Azure.NotificationHubs.DotNetCore.Tests | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Net; | ||
using System.Net.Http; | ||
using System.Net.Sockets; | ||
using System.Threading.Tasks; | ||
using Microsoft.Azure.NotificationHubs.Messaging; | ||
using RichardSzalay.MockHttp; | ||
using Xunit; | ||
|
||
public class NamespaceManagerRetryPolicyTests | ||
{ | ||
private readonly string _connectionString; | ||
private readonly string _hubName; | ||
private NamespaceManager _namespaceClient; | ||
private MockHttpMessageHandler _mockHttp; | ||
private const string _hubResponse = "<entry xmlns=\"http://www.w3.org/2005/Atom\"><id>https://sample.servicebus.windows.net/sample?api-version=2017-04</id><title type=\"text\">sample</title><published>2020-07-02T18:03:10Z</published><updated>2020-07-02T18:03:11Z</updated><author><name>sample</name></author><link rel=\"self\" href=\"https://sample.servicebus.windows.net/sample?api-version=2017-04\"/><content type=\"application/xml\"><NotificationHubDescription xmlns=\"http://schemas.microsoft.com/netservices/2010/10/servicebus/connect\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><RegistrationTtl>P10675199DT2H48M5.4775807S</RegistrationTtl><AuthorizationRules><AuthorizationRule i:type=\"SharedAccessAuthorizationRule\"><ClaimType>SharedAccessKey</ClaimType><ClaimValue>None</ClaimValue><Rights><AccessRights>Listen</AccessRights></Rights><CreatedTime>2020-07-02T18:03:10.772227Z</CreatedTime><ModifiedTime>2020-07-02T18:03:10.772227Z</ModifiedTime><KeyName>DefaultListenSharedAccessSignature</KeyName><PrimaryKey>xxxx</PrimaryKey><SecondaryKey>xxxx</SecondaryKey></AuthorizationRule><AuthorizationRule i:type=\"SharedAccessAuthorizationRule\"><ClaimType>SharedAccessKey</ClaimType><ClaimValue>None</ClaimValue><Rights><AccessRights>Listen</AccessRights><AccessRights>Manage</AccessRights><AccessRights>Send</AccessRights></Rights><CreatedTime>2020-07-02T18:03:10.772227Z</CreatedTime><ModifiedTime>2020-07-02T18:03:10.772227Z</ModifiedTime><KeyName>DefaultFullSharedAccessSignature</KeyName><PrimaryKey>xxxx</PrimaryKey><SecondaryKey>xxxx</SecondaryKey></AuthorizationRule></AuthorizationRules></NotificationHubDescription></content></entry>"; | ||
|
||
public NamespaceManagerRetryPolicyTests() | ||
{ | ||
_connectionString = "Endpoint=sb://sample.servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=xxxxxx"; | ||
_hubName = "hub-name"; | ||
_mockHttp = new MockHttpMessageHandler(); | ||
_namespaceClient = new NamespaceManager(_connectionString, new NotificationHubSettings | ||
{ | ||
HttpClient = _mockHttp.ToHttpClient(), | ||
RetryOptions = new NotificationHubRetryOptions | ||
{ | ||
Delay = TimeSpan.FromMilliseconds(10) | ||
} | ||
}); | ||
} | ||
|
||
[Theory] | ||
[InlineData(HttpStatusCode.InternalServerError)] | ||
[InlineData(HttpStatusCode.ServiceUnavailable)] | ||
[InlineData(HttpStatusCode.GatewayTimeout)] | ||
[InlineData(HttpStatusCode.RequestTimeout)] | ||
public async Task RetryPolicyRetriesOnTransientErrorInPut(HttpStatusCode errorCode) | ||
{ | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name") | ||
.Respond(errorCode); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name") | ||
.Respond(HttpStatusCode.OK, "application/xml", _hubResponse); | ||
|
||
await _namespaceClient.CreateNotificationHubAsync(_hubName); | ||
|
||
_mockHttp.VerifyNoOutstandingExpectation(); | ||
} | ||
|
||
[Fact] | ||
public async Task RetryPolicyRetriesConnectionErrors() | ||
{ | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name") | ||
.Throw(new TimeoutException()); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name") | ||
.Throw(new HttpRequestException("", new SocketException((int)SocketError.TimedOut))); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name") | ||
.Respond(HttpStatusCode.OK, "application/xml", _hubResponse); | ||
|
||
await _namespaceClient.CreateNotificationHubAsync(_hubName); | ||
|
||
_mockHttp.VerifyNoOutstandingExpectation(); | ||
} | ||
|
||
[Fact] | ||
public async Task RetryPolicyRetriesOnThrottling() | ||
{ | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name") | ||
.Respond((HttpStatusCode)403, new Dictionary<string, string> { { "Retry-After", "1" }}, new StringContent("")); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name") | ||
.Respond((HttpStatusCode)429, new Dictionary<string, string> { { "Retry-After", "1" } }, new StringContent("")); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name") | ||
.Respond(HttpStatusCode.OK, "application/xml", _hubResponse); | ||
|
||
await _namespaceClient.CreateNotificationHubAsync(_hubName); | ||
|
||
_mockHttp.VerifyNoOutstandingExpectation(); | ||
} | ||
|
||
[Fact] | ||
public async Task RetryPolicyRethrowsNonTransientErrors() | ||
{ | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name") | ||
.Respond(HttpStatusCode.NotFound); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name") | ||
.Respond(HttpStatusCode.OK, "application/xml", _hubResponse); | ||
|
||
await Assert.ThrowsAsync<MessagingEntityNotFoundException>(() => _namespaceClient.CreateNotificationHubAsync(_hubName)); | ||
} | ||
|
||
[Fact] | ||
public async Task RetryPolicyGivesUpAfterTimeout() | ||
{ | ||
_namespaceClient = new NamespaceManager(_connectionString, new NotificationHubSettings | ||
{ | ||
MessageHandler = _mockHttp, | ||
RetryOptions = new NotificationHubRetryOptions | ||
{ | ||
Delay = TimeSpan.FromMilliseconds(10), | ||
MaxRetries = 1 | ||
} | ||
}); | ||
|
||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name") | ||
.Throw(new TimeoutException()); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name") | ||
.Throw(new TimeoutException()); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name") | ||
.Respond(HttpStatusCode.OK, "application/xml", _hubResponse); | ||
|
||
await Assert.ThrowsAsync<TimeoutException>(() => _namespaceClient.CreateNotificationHubAsync(_hubName)); | ||
} | ||
} | ||
} |
140 changes: 140 additions & 0 deletions
140
...icrosoft.Azure.NotificationHubs.DotNetCore.Tests/NotificationHubClientRetryPolicyTests.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,140 @@ | ||
//------------------------------------------------------------ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. See License.txt in the project root for | ||
// license information. | ||
//------------------------------------------------------------ | ||
|
||
namespace Microsoft.Azure.NotificationHubs.DotNetCore.Tests | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Net; | ||
using System.Net.Http; | ||
using System.Net.Sockets; | ||
using System.Threading.Tasks; | ||
using Microsoft.Azure.NotificationHubs.Messaging; | ||
using RichardSzalay.MockHttp; | ||
using Xunit; | ||
|
||
public class NotificationHubClientRetryPolicyTests | ||
{ | ||
private readonly string _connectionString; | ||
private readonly string _hubName; | ||
private NotificationHubClient _nhClient; | ||
private MockHttpMessageHandler _mockHttp; | ||
|
||
public NotificationHubClientRetryPolicyTests() | ||
{ | ||
_connectionString = "Endpoint=sb://sample.servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=xxxxxx"; | ||
_hubName = "hub-name"; | ||
_mockHttp = new MockHttpMessageHandler(); | ||
_nhClient = new NotificationHubClient(_connectionString, _hubName, new NotificationHubSettings | ||
{ | ||
HttpClient = _mockHttp.ToHttpClient(), | ||
RetryOptions = new NotificationHubRetryOptions | ||
{ | ||
Delay = TimeSpan.FromMilliseconds(10) | ||
} | ||
}); | ||
} | ||
|
||
[Theory] | ||
[InlineData(HttpStatusCode.InternalServerError)] | ||
[InlineData(HttpStatusCode.ServiceUnavailable)] | ||
[InlineData(HttpStatusCode.GatewayTimeout)] | ||
[InlineData(HttpStatusCode.RequestTimeout)] | ||
public async Task RetryPolicyRetriesOnTransientErrorInSend(HttpStatusCode errorCode) | ||
{ | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name/messages") | ||
.Respond(errorCode); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name/messages") | ||
.Respond(HttpStatusCode.OK); | ||
|
||
await _nhClient.SendDirectNotificationAsync(new FcmNotification("{}"), "123"); | ||
|
||
_mockHttp.VerifyNoOutstandingExpectation(); | ||
} | ||
|
||
[Theory] | ||
[InlineData(HttpStatusCode.InternalServerError)] | ||
[InlineData(HttpStatusCode.ServiceUnavailable)] | ||
[InlineData(HttpStatusCode.GatewayTimeout)] | ||
[InlineData(HttpStatusCode.RequestTimeout)] | ||
public async Task RetryPolicyRetriesOnTransientErrorInRegister(HttpStatusCode errorCode) | ||
{ | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name/registrations") | ||
.Respond(errorCode); | ||
var registrationXml = "<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:a=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\"><id>https://sample.servicebus.windows.net/hub-name/registrations/123456?api-version=2017-04</id><title type=\"text\">4757098718499783238-6462592605842469809-1</title><published>2019-05-13T17:12:18Z</published><updated>2019-05-13T17:12:18Z</updated><link rel=\"self\" href=\"https://sdk-sample-namespace.servicebus.windows.net/sdk-sample-nh/registrations/4757098718499783238-6462592605842469809-1?api-version=2017-04\"/><content type=\"application/xml\"><GcmRegistrationDescription xmlns=\"http://schemas.microsoft.com/netservices/2010/10/servicebus/connect\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><ETag>2</ETag><ExpirationTime>9999-12-31T23:59:59.999</ExpirationTime><RegistrationId>4757098718499783238-6462592605842469809-1</RegistrationId><Tags>tag2</Tags><GcmRegistrationId>amzn1.adm-registration.v2.123</GcmRegistrationId></GcmRegistrationDescription></content></entry>"; | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name/registrations") | ||
.Respond("application/atom+xml", registrationXml); | ||
|
||
var registration = await _nhClient.CreateFcmNativeRegistrationAsync("123456"); | ||
|
||
_mockHttp.VerifyNoOutstandingExpectation(); | ||
} | ||
|
||
[Fact] | ||
public async Task RetryPolicyRetriesConnectionErrors() | ||
{ | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name/messages") | ||
.Throw(new TimeoutException()); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name/messages") | ||
.Throw(new HttpRequestException("", new SocketException((int)SocketError.TimedOut))); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name/messages") | ||
.Respond(HttpStatusCode.OK); | ||
|
||
await _nhClient.SendDirectNotificationAsync(new FcmNotification("{}"), "123"); | ||
|
||
_mockHttp.VerifyNoOutstandingExpectation(); | ||
} | ||
|
||
[Fact] | ||
public async Task RetryPolicyRetriesOnThrottling() | ||
{ | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name/messages") | ||
.Respond((HttpStatusCode)403, new Dictionary<string, string> { { "Retry-After", "1" }}, new StringContent("")); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name/messages") | ||
.Respond((HttpStatusCode)429, new Dictionary<string, string> { { "Retry-After", "1" } }, new StringContent("")); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name/messages") | ||
.Respond(HttpStatusCode.OK); | ||
|
||
await _nhClient.SendDirectNotificationAsync(new FcmNotification("{}"), "123"); | ||
|
||
_mockHttp.VerifyNoOutstandingExpectation(); | ||
} | ||
|
||
[Fact] | ||
public async Task RetryPolicyRethrowsNonTransientErrors() | ||
{ | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name/messages") | ||
.Respond(HttpStatusCode.NotFound); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name/messages") | ||
.Respond(HttpStatusCode.OK); | ||
|
||
await Assert.ThrowsAsync<MessagingEntityNotFoundException>(() => _nhClient.SendDirectNotificationAsync(new FcmNotification("{}"), "123")); | ||
} | ||
|
||
[Fact] | ||
public async Task RetryPolicyGivesUpAfterTimeout() | ||
{ | ||
_nhClient = new NotificationHubClient(_connectionString, _hubName, new NotificationHubSettings | ||
{ | ||
MessageHandler = _mockHttp, | ||
RetryOptions = new NotificationHubRetryOptions | ||
{ | ||
Delay = TimeSpan.FromMilliseconds(10), | ||
MaxRetries = 1 | ||
} | ||
}); | ||
|
||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name/messages") | ||
.Throw(new TimeoutException()); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name/messages") | ||
.Throw(new TimeoutException()); | ||
_mockHttp.Expect("https://sample.servicebus.windows.net/hub-name/messages") | ||
.Respond(HttpStatusCode.OK); | ||
|
||
await Assert.ThrowsAsync<TimeoutException>(() => _nhClient.SendDirectNotificationAsync(new FcmNotification("{}"), "123")); | ||
} | ||
} | ||
} |
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
8 changes: 7 additions & 1 deletion
8
...ft.Azure.NotificationHubs.DotNetCore.Tests/NotificationHubConnectionStringBuilderTests.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
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.