Skip to content

Commit

Permalink
Merge pull request #2017 from ably/fix/2009-fallbacks-in-custom-env
Browse files Browse the repository at this point in the history
[ECO-5190] Fallbacks in custom environment
  • Loading branch information
maratal authored Feb 10, 2025
2 parents 11f6787 + e58e13a commit 022fee0
Show file tree
Hide file tree
Showing 4 changed files with 237 additions and 49 deletions.
2 changes: 1 addition & 1 deletion Source/ARTDefault.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ + (NSArray*)fallbackHostsWithEnvironment:(NSString *)environment {
NSArray<NSString *> * fallbacks = @[@"a", @"b", @"c", @"d", @"e"];
NSString *prefix = @"";
NSString *suffix = @"";
if (environment && ![[environment stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:@""] && ![environment isEqualToString:ARTDefaultProduction]) {
if (environment && ![environment isEqualToString:@""] && ![environment isEqualToString:ARTDefaultProduction]) {
prefix = [NSString stringWithFormat:@"%@-", environment];
suffix = @"-fallback";
}
Expand Down
66 changes: 41 additions & 25 deletions Source/ARTRealtime.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#import "ARTMessage.h"
#import "ARTClientOptions.h"
#import "ARTClientOptions+TestConfiguration.h"
#import "ARTClientOptions+Private.h"
#import "ARTTestClientOptions.h"
#import "ARTChannelOptions.h"
#import "ARTPresenceMessage.h"
Expand Down Expand Up @@ -1499,13 +1500,31 @@ - (BOOL)reconnectWithFallback {
}
}

- (BOOL)shouldRetryWithFallback:(ARTRealtimeTransportError *)error {
if (
(error.type == ARTRealtimeTransportErrorTypeBadResponse && error.badResponseCode >= 500 && error.badResponseCode <= 504) ||
error.type == ARTRealtimeTransportErrorTypeHostUnreachable ||
error.type == ARTRealtimeTransportErrorTypeTimeout
) {
return YES;
- (BOOL)shouldRetryWithFallbackForError:(ARTRealtimeTransportError *)error options:(ARTClientOptions *)options {
if ((error.type == ARTRealtimeTransportErrorTypeBadResponse && error.badResponseCode >= 500 && error.badResponseCode <= 504) ||
error.type == ARTRealtimeTransportErrorTypeHostUnreachable || error.type == ARTRealtimeTransportErrorTypeTimeout) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// RTN17b3
if (options.fallbackHostsUseDefault) {
return YES;
}
#pragma clang diagnostic pop

// RTN17b1
if (!(options.hasCustomRealtimeHost || options.hasCustomPort || options.hasCustomTlsPort)) {
return YES;
}

// RTN17b2
if (options.fallbackHosts) {
return YES;
}

// RSC15g2
if (options.hasEnvironmentDifferentThanProduction) {
return YES;
}
}
return NO;
}
Expand Down Expand Up @@ -1648,28 +1667,25 @@ - (void)realtimeTransportFailed:(id<ARTRealtimeTransport>)transport withError:(A

ARTLogDebug(self.logger, @"R:%p realtime transport failed: %@", self, transportError);

if ([self shouldRetryWithFallback:transportError]) {
ARTErrorInfo *const errorInfo = [ARTErrorInfo createFromNSError:transportError.error];
ARTConnectionStateChangeParams *const params = [[ARTConnectionStateChangeParams alloc] initWithErrorInfo:errorInfo];

ARTClientOptions *const clientOptions = [self getClientOptions];

if ([self shouldRetryWithFallbackForError:transportError options:clientOptions]) {
ARTLogDebug(self.logger, @"R:%p host is down; can retry with fallback host", self);
if (!_fallbacks && [transportError.url.host isEqualToString:[ARTDefault realtimeHost]]) {
ARTClientOptions *const clientOptions = [self getClientOptions];
if (!_fallbacks) {
NSArray *hosts = [ARTFallbackHosts hostsFromOptions:clientOptions];
self->_fallbacks = [[ARTFallback alloc] initWithFallbackHosts:hosts shuffleArray:clientOptions.testOptions.shuffleArray];
if (self->_fallbacks != nil) {
[self reconnectWithFallback];
} else {
ARTErrorInfo *const errorInfo = [ARTErrorInfo createFromNSError:transportError.error];
ARTConnectionStateChangeParams *const params = [[ARTConnectionStateChangeParams alloc] initWithErrorInfo:errorInfo];
[self performTransitionToState:ARTRealtimeFailed withParams:params];
}
return;
} else if (_fallbacks && [self reconnectWithFallback]) {
return;
_fallbacks = [[ARTFallback alloc] initWithFallbackHosts:hosts shuffleArray:clientOptions.testOptions.shuffleArray];
}
if (_fallbacks) {
[self reconnectWithFallback];
} else {
[self performTransitionToState:ARTRealtimeFailed withParams:params];
}
} else {
[self performTransitionToDisconnectedOrSuspendedWithParams:params];
}

ARTErrorInfo *const errorInfo = [ARTErrorInfo createFromNSError:transportError.error];
ARTConnectionStateChangeParams *const params = [[ARTConnectionStateChangeParams alloc] initWithErrorInfo:errorInfo];
[self performTransitionToDisconnectedOrSuspendedWithParams:params];
}

- (void)realtimeTransportNeverConnected:(id<ARTRealtimeTransport>)transport {
Expand Down
2 changes: 1 addition & 1 deletion Source/include/Ably/ARTClientOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* Enables a [custom environment](https://ably.com/docs/platform-customization) to be used with the Ably service.
*/
@property (readwrite, nonatomic) NSString *environment;
@property (readwrite, nonatomic, nullable) NSString *environment;

/**
* When `false`, the client will use an insecure connection. The default is `true`, meaning a TLS connection will be used to connect to Ably.
Expand Down
Loading

0 comments on commit 022fee0

Please sign in to comment.