Ben Copsey

Added automatic retry for timeouts

... ... @@ -324,6 +324,13 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
// When set to yes, this request will create a thread to run itself in
// On Snow Leopard, requests using a queue will always run in a background thread, so this does nothing when using a queue on that platform
BOOL shouldRunInBackgroundThread;
// Set to allow a request to automatically retry itself on timeout
// Default is zero - timeout will stop the request
int numberOfTimesToRetryOnTimeout;
// The number of times this request has retried (when numberOfTimesToRetryOnTimeout > 0)
int retryCount;
}
#pragma mark init / dealloc
... ... @@ -374,9 +381,6 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
#pragma mark request logic
// Start the read stream. Called by loadRequest, and again to restart the request when authentication is needed
- (void)startRequest;
// Call to delete the temporary file used during a file download (if it exists)
// No need to call this if the request succeeds - it is removed automatically
- (void)removeTemporaryDownloadFile;
... ... @@ -660,4 +664,6 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
@property (assign, readonly) BOOL isSynchronous;
@property (assign, readonly) BOOL inProgress;
@property (assign) BOOL shouldRunInBackgroundThread;
@property (assign) int numberOfTimesToRetryOnTimeout;
@property (assign, readonly) int retryCount;
@end
... ...
... ... @@ -21,7 +21,7 @@
#import "ASIInputStream.h"
// Automatically set on build
NSString *ASIHTTPRequestVersion = @"v1.2-45 2009-12-18";
NSString *ASIHTTPRequestVersion = @"v1.2-51 2009-12-19";
NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain";
... ... @@ -106,13 +106,16 @@ static BOOL isiPhoneOS2;
- (void)destroyReadStream;
- (void)scheduleReadStream;
- (void)scheduleReadStream;
- (void)unscheduleReadStream;
- (BOOL)askDelegateForCredentials;
- (BOOL)askDelegateForProxyCredentials;
+ (void)measureBandwidthUsage;
+ (void)recordBandwidthUsage;
// Start the read stream. Called by loadRequest, and again to restart the request when authentication is needed
- (void)startRequest;
#if TARGET_OS_IPHONE
+ (void)registerForNetworkReachabilityNotifications;
+ (void)unsubscribeFromNetworkReachabilityNotifications;
... ... @@ -150,6 +153,7 @@ static BOOL isiPhoneOS2;
@property (retain) NSString *responseStatusMessage;
@property (assign) BOOL isSynchronous;
@property (assign) BOOL inProgress;
@property (assign) int retryCount;
@end
... ... @@ -533,7 +537,6 @@ static BOOL isiPhoneOS2;
[pool release];
}
#pragma mark concurrency
- (BOOL)isConcurrent
... ... @@ -751,7 +754,7 @@ static BOOL isiPhoneOS2;
[self setTotalBytesRead:0];
[self setLastBytesRead:0];
// If we're retrying a request after an authentication failure, let's remove any progress we made
// If we're retrying a request, let's remove any progress we made
if ([self lastBytesSent] > 0) {
[self removeUploadProgressSoFar];
}
... ... @@ -967,6 +970,15 @@ static BOOL isiPhoneOS2;
// This is to workaround the fact that kCFStreamPropertyHTTPRequestBytesWrittenCount is the amount written to the buffer, not the amount actually sent
// This workaround prevents erroneous timeouts in low bandwidth situations (eg iPhone)
if (totalBytesSent || postLength <= uploadBufferSize || (uploadBufferSize > 0 && totalBytesSent > uploadBufferSize)) {
// Do we need to auto-retry this request?
if ([self numberOfTimesToRetryOnTimeout] > [self retryCount]) {
[self setRetryCount:[self retryCount]+1];
[self unscheduleReadStream];
[[self cancelledLock] unlock];
[self startRequest];
return;
}
[self failWithError:ASIRequestTimedOutError];
[self cancelLoad];
[self setComplete:YES];
... ... @@ -3356,6 +3368,8 @@ static BOOL isiPhoneOS2;
@synthesize isSynchronous;
@synthesize inProgress;
@synthesize shouldRunInBackgroundThread;
@synthesize numberOfTimesToRetryOnTimeout;
@synthesize retryCount;
@end
... ...
... ... @@ -57,4 +57,5 @@
#if TARGET_OS_IPHONE
- (void)testReachability;
#endif
- (void)testAutomaticRetry;
@end
... ...
... ... @@ -1216,4 +1216,15 @@
}
}
#endif
- (void)testAutomaticRetry
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request setTimeOutSeconds:0.001];
[request setNumberOfTimesToRetryOnTimeout:5];
[request startSynchronous];
GHAssertNotNil([request error],@"Request failed to timeout, cannot proceed with test");
BOOL success = ([request retryCount] == 5);
GHAssertTrue(success,@"Request failed to retry on timeout");
}
@end
\ No newline at end of file
... ...