Skip to content

Instantly share code, notes, and snippets.

@SteveTrewick
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SteveTrewick/28eca55cf4fbcb0aa884 to your computer and use it in GitHub Desktop.
Save SteveTrewick/28eca55cf4fbcb0aa884 to your computer and use it in GitHub Desktop.
Recursive completion handlers with retry and back off using some higher order functions via blocks. Not sure about this at all, but it was a way to spend an afternoon, eh ?
#import <Foundation/Foundation.h>
typedef void(^CompletionHandler)(id connection, id result, NSError * error);
typedef BOOL(^Counter)();
typedef void(^RequestWrapper)(CompletionHandler);
@interface SMRequestFoo : NSObject
+(void)
request :(id ) thing
completion:(CompletionHandler) completion;
@end
@implementation SMRequestFoo
+(void)
request :(id ) thing
completion:(CompletionHandler) completion
{
static int count_through = 0;
NSError * error = count_through > 7 ? nil: [NSError errorWithDomain:@"Domain" code:42 userInfo:nil];
id result = nil;
id connection = nil;
count_through++;
dispatch_async(dispatch_get_main_queue(),^{
completion(connection, result, error);
});
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
dispatch_queue_t requestQ = dispatch_queue_create("requestQ", 0);
Counter (^CounterBuilder)(int) = ^Counter(int max){
return ^BOOL{
static int retries = 0;
return retries++ >= max ? YES : NO;
};
};
RequestWrapper (^RequestWrapperBuilder)(id) = (
^RequestWrapper(id obj){
return ^void(CompletionHandler ch){
[SMRequestFoo
request : obj
completion: ch
];
};
}
);
int (^BackOffLinear)() = ^int{
static int delay = 0;
return delay++;
};
Counter retry_count_exceeded = CounterBuilder(9);
RequestWrapper request_with_completion = RequestWrapperBuilder(nil);
__weak __block CompletionHandler wcomp;
CompletionHandler comp = ^(id connection, id result, NSError * error){
if (error) {
if( retry_count_exceeded() ) {
NSLog(@"Failed at max retries, we're done here");
}
else {
NSLog(@"Retry...");
__strong CompletionHandler scomp = wcomp;
dispatch_async( requestQ, ^{
sleep(BackOffLinear()); // hmmmmm...
request_with_completion(scomp);
});
}
}
else { NSLog(@"OK all good now, moving on for other things"); }
};
wcomp = comp;
dispatch_async(requestQ, ^{
request_with_completion(wcomp);
});
// Keep on truckin'
[[NSRunLoop currentRunLoop] run];
}
return 0;
}
/*
2014-06-25 15:32:59.586 completion_retry_spike_1[3040:303] Retry...
2014-06-25 15:32:59.588 completion_retry_spike_1[3040:303] Retry...
2014-06-25 15:33:00.589 completion_retry_spike_1[3040:303] Retry...
2014-06-25 15:33:02.590 completion_retry_spike_1[3040:303] Retry...
2014-06-25 15:33:05.592 completion_retry_spike_1[3040:303] Retry...
2014-06-25 15:33:09.594 completion_retry_spike_1[3040:303] Retry...
2014-06-25 15:33:14.596 completion_retry_spike_1[3040:303] Retry...
2014-06-25 15:33:20.598 completion_retry_spike_1[3040:303] Retry...
2014-06-25 15:33:27.599 completion_retry_spike_1[3040:303] OK all good now, moving on for other things
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment