diff --git a/Source/ARTClientOptions.h b/Source/ARTClientOptions.h index ecf0e0ee0..4708b47f3 100644 --- a/Source/ARTClientOptions.h +++ b/Source/ARTClientOptions.h @@ -73,7 +73,7 @@ ART_ASSUME_NONNULL_BEGIN /** Optionally allows one or more fallback hosts to be used instead of the default fallback hosts. */ -@property (art_nullable, nonatomic, copy) NSArray *fallbackHosts; +@property (art_nullable, nonatomic, copy) __GENERIC(NSArray, NSString *) *fallbackHosts; - (BOOL)isBasicAuth; - (NSURL *)restUrl; diff --git a/Source/ARTFallback.h b/Source/ARTFallback.h index 0a696725a..f2e78fb6c 100644 --- a/Source/ARTFallback.h +++ b/Source/ARTFallback.h @@ -21,7 +21,10 @@ extern int (^ARTFallback_getRandomHostIndex)(int count); } -- (id)initWithFallbackHosts:(art_nullable NSArray *)fallbackHosts; +/** + Init with fallback hosts array. + */ +- (instancetype)initWithFallbackHosts:(art_nullable __GENERIC(NSArray, NSString *) *)fallbackHosts; /** returns a random fallback host, returns null when all hosts have been popped. diff --git a/Source/ARTFallback.m b/Source/ARTFallback.m index 4a45954a0..2444f7ec0 100644 --- a/Source/ARTFallback.m +++ b/Source/ARTFallback.m @@ -25,15 +25,15 @@ @interface ARTFallback () @implementation ARTFallback -- (id)initWithFallbackHosts:(art_nullable NSArray *)fallbackHosts { +- (instancetype)initWithFallbackHosts:(art_nullable __GENERIC(NSArray, NSString *) *)fallbackHosts { self = [super init]; - if(self) { + if (self) { if (fallbackHosts != nil && fallbackHosts.count == 0) { return nil; } - + self.hosts = [NSMutableArray array]; - NSMutableArray * hostArray =[[NSMutableArray alloc] initWithArray: fallbackHosts ? fallbackHosts : [ARTDefault fallbackHosts]]; + NSMutableArray * hostArray = [[NSMutableArray alloc] initWithArray: fallbackHosts ? fallbackHosts : [ARTDefault fallbackHosts]]; size_t count = [hostArray count]; for (int i=0; i *)fallbackHosts { return self; } -- (id)init { +- (instancetype)init { return [self initWithFallbackHosts:nil]; } diff --git a/Spec/RestClient.swift b/Spec/RestClient.swift index 4a561f3fa..6db486efd 100644 --- a/Spec/RestClient.swift +++ b/Spec/RestClient.swift @@ -788,6 +788,37 @@ class RestClient: QuickSpec { expect(resultFallbackHosts).to(equal(expectedFallbackHosts)) } + + it("use custom fallback hosts if set") { + let options = ARTClientOptions(key: "xxxx:xxxx") + options.httpMaxRetryCount = 10 + let customFallbackHosts = ["j.ably-realtime.com", + "i.ably-realtime.com", + "h.ably-realtime.com", + "g.ably-realtime.com", + "f.ably-realtime.com"] + options.fallbackHosts = customFallbackHosts + let client = ARTRest(options: options) + client.httpExecutor = testHTTPExecutor + testHTTPExecutor.http = MockHTTP(network: .HostUnreachable) + let channel = client.channels.get("test") + + waitUntil(timeout: testTimeout) { done in + channel.publish(nil, data: "nil") { _ in + done() + } + } + + expect(testHTTPExecutor.requests).to(haveCount(customFallbackHosts.count + 1)) + + let extractHostname = { (request: NSMutableURLRequest) in + NSRegularExpression.extract(request.URL!.absoluteString, pattern: "[f-j].ably-realtime.com") + } + let resultFallbackHosts = testHTTPExecutor.requests.flatMap(extractHostname) + let expectedFallbackHosts = expectedHostOrder.map { customFallbackHosts[$0] } + + expect(resultFallbackHosts).to(equal(expectedFallbackHosts)) + } it("until all fallback hosts have been tried") { let options = ARTClientOptions(key: "xxxx:xxxx") diff --git a/Tests/ARTFallbackTest.m b/Tests/ARTFallbackTest.m index 92663e6ab..eed3fbb92 100644 --- a/Tests/ARTFallbackTest.m +++ b/Tests/ARTFallbackTest.m @@ -43,4 +43,40 @@ - (void)testAllHostsIncludedOnce { } } +- (void)testCustomFallbackHosts { + __weak int (^originalARTFallback_getRandomHostIndex)(int) = ARTFallback_getRandomHostIndex; + @try { + ARTFallback_getRandomHostIndex = ^() { + __block NSArray *hostIndexes = @[@1, @2, @0, @1, @0, @0]; + __block int i = 0; + return ^int(int count) { + NSNumber *hostIndex = hostIndexes[i]; + i++; + return hostIndex.intValue; + }; + }(); + + NSArray *customHosts = @[@"testA.ably.com", + @"testB.ably.com", + @"testC.ably.com", + @"testD.ably.com", + @"testE.ably.com", + @"testF.ably.com"]; + + ARTFallback *f = [[ARTFallback alloc] initWithFallbackHosts:customHosts]; + + XCTAssertEqualObjects([f popFallbackHost], @"testF.ably.com"); + XCTAssertEqualObjects([f popFallbackHost], @"testC.ably.com"); + XCTAssertEqualObjects([f popFallbackHost], @"testE.ably.com"); + XCTAssertEqualObjects([f popFallbackHost], @"testA.ably.com"); + XCTAssertEqualObjects([f popFallbackHost], @"testD.ably.com"); + XCTAssertEqualObjects([f popFallbackHost], @"testB.ably.com"); + + XCTAssertEqual([f popFallbackHost], nil); + } + @finally { + ARTFallback_getRandomHostIndex = originalARTFallback_getRandomHostIndex; + } +} + @end