Merge branch 'charlesmchen/messageSendFatalErrors'
This commit is contained in:
commit
0bbe73e110
|
@ -54,7 +54,12 @@ void AssertIsOnSendingQueue()
|
||||||
|
|
||||||
static void *kNSError_MessageSender_IsRetryable = &kNSError_MessageSender_IsRetryable;
|
static void *kNSError_MessageSender_IsRetryable = &kNSError_MessageSender_IsRetryable;
|
||||||
static void *kNSError_MessageSender_ShouldBeIgnoredForGroups = &kNSError_MessageSender_ShouldBeIgnoredForGroups;
|
static void *kNSError_MessageSender_ShouldBeIgnoredForGroups = &kNSError_MessageSender_ShouldBeIgnoredForGroups;
|
||||||
|
static void *kNSError_MessageSender_IsFatal = &kNSError_MessageSender_IsFatal;
|
||||||
|
|
||||||
|
// isRetryable and isFatal are opposites but not redundant.
|
||||||
|
//
|
||||||
|
// If a group message send fails, the send will be retried if any of the errors were retryable UNLESS
|
||||||
|
// any of the errors were fatal. Fatal errors trump retryable errors.
|
||||||
@implementation NSError (OWSMessageSender)
|
@implementation NSError (OWSMessageSender)
|
||||||
|
|
||||||
- (BOOL)isRetryable
|
- (BOOL)isRetryable
|
||||||
|
@ -84,6 +89,19 @@ static void *kNSError_MessageSender_ShouldBeIgnoredForGroups = &kNSError_Message
|
||||||
objc_setAssociatedObject(self, kNSError_MessageSender_ShouldBeIgnoredForGroups, @(value), OBJC_ASSOCIATION_COPY);
|
objc_setAssociatedObject(self, kNSError_MessageSender_ShouldBeIgnoredForGroups, @(value), OBJC_ASSOCIATION_COPY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)isFatal
|
||||||
|
{
|
||||||
|
NSNumber *value = objc_getAssociatedObject(self, kNSError_MessageSender_IsFatal);
|
||||||
|
// This value will NOT always be set for all errors by the time we query it's value.
|
||||||
|
// Default to NOT fatal.
|
||||||
|
return value ? [value boolValue] : NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setIsFatal:(BOOL)value
|
||||||
|
{
|
||||||
|
objc_setAssociatedObject(self, kNSError_MessageSender_IsFatal, @(value), OBJC_ASSOCIATION_COPY);
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
@ -266,7 +284,7 @@ NSUInteger const OWSSendMessageOperationMaxRetries = 4;
|
||||||
RetryableFailureHandler retryableFailureHandler = ^(NSError *_Nonnull error) {
|
RetryableFailureHandler retryableFailureHandler = ^(NSError *_Nonnull error) {
|
||||||
DDLogInfo(@"%@ Sending failed.", self.tag);
|
DDLogInfo(@"%@ Sending failed.", self.tag);
|
||||||
|
|
||||||
if (![error isRetryable]) {
|
if (![error isRetryable] || [error isFatal]) {
|
||||||
DDLogInfo(@"%@ Skipping retry due to terminal error: %@", self.tag, error);
|
DDLogInfo(@"%@ Skipping retry due to terminal error: %@", self.tag, error);
|
||||||
self.failureHandler(error);
|
self.failureHandler(error);
|
||||||
return;
|
return;
|
||||||
|
@ -748,6 +766,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||||
id failureResult = groupSendFuture.forceGetFailure;
|
id failureResult = groupSendFuture.forceGetFailure;
|
||||||
if ([failureResult isKindOfClass:[NSError class]]) {
|
if ([failureResult isKindOfClass:[NSError class]]) {
|
||||||
NSError *error = failureResult;
|
NSError *error = failureResult;
|
||||||
|
|
||||||
// Some errors should be ignored when sending messages
|
// Some errors should be ignored when sending messages
|
||||||
// to groups. See discussion on
|
// to groups. See discussion on
|
||||||
// NSError (OWSMessageSender) category.
|
// NSError (OWSMessageSender) category.
|
||||||
|
@ -755,6 +774,15 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some errors should never be retried, in order to avoid
|
||||||
|
// hitting rate limits, for example. Unfortunately, since
|
||||||
|
// group send retry is all-or-nothing, we need to fail
|
||||||
|
// immediately even if some of the other recipients had
|
||||||
|
// retryable errors.
|
||||||
|
if ([error isFatal]) {
|
||||||
|
failureHandler(error);
|
||||||
|
}
|
||||||
|
|
||||||
if ([error isRetryable] && !firstRetryableError) {
|
if ([error isRetryable] && !firstRetryableError) {
|
||||||
firstRetryableError = error;
|
firstRetryableError = error;
|
||||||
} else if (![error isRetryable] && !firstNonRetryableError) {
|
} else if (![error isRetryable] && !firstNonRetryableError) {
|
||||||
|
@ -859,6 +887,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||||
// Key will continue to be unaccepted, so no need to retry. It'll only cause us to hit the Pre-Key request
|
// Key will continue to be unaccepted, so no need to retry. It'll only cause us to hit the Pre-Key request
|
||||||
// rate limit
|
// rate limit
|
||||||
[error setIsRetryable:NO];
|
[error setIsRetryable:NO];
|
||||||
|
// Avoid the "Too many failures with this contact" error rate limiting.
|
||||||
|
[error setIsFatal:YES];
|
||||||
return failureHandler(error);
|
return failureHandler(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -869,6 +899,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||||
|
|
||||||
// We're already rate-limited. No need to exacerbate the problem.
|
// We're already rate-limited. No need to exacerbate the problem.
|
||||||
[error setIsRetryable:NO];
|
[error setIsRetryable:NO];
|
||||||
|
// Avoid exacerbating the rate limiting.
|
||||||
|
[error setIsFatal:YES];
|
||||||
return failureHandler(error);
|
return failureHandler(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue