Skip to content

Commit

Permalink
Merge 455d48d into a01ca99
Browse files Browse the repository at this point in the history
  • Loading branch information
rastersize committed Feb 22, 2016
2 parents a01ca99 + 455d48d commit 17b1660
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 123 deletions.
22 changes: 10 additions & 12 deletions SPTDataLoader/SPTDataLoader.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@

@interface SPTDataLoader ()

@property (nonatomic, strong) NSHashTable<id<SPTDataLoaderCancellationToken>> *cancellationTokens;
@property (nonatomic, strong) NSMutableArray<SPTDataLoaderRequest *> *requests;
@property (nonatomic, strong, readonly) NSHashTable<id<SPTDataLoaderCancellationToken>> *cancellationTokens;
@property (nonatomic, strong, readonly) NSMutableArray<SPTDataLoaderRequest *> *requests;

@end

Expand All @@ -46,16 +46,14 @@ + (instancetype)dataLoaderWithRequestResponseHandlerDelegate:(id<SPTDataLoaderRe

- (instancetype)initWithRequestResponseHandlerDelegate:(id<SPTDataLoaderRequestResponseHandlerDelegate>)requestResponseHandlerDelegate
{
if (!(self = [super init])) {
return nil;
self = [super init];
if (self) {
_requestResponseHandlerDelegate = requestResponseHandlerDelegate;

_cancellationTokens = [NSHashTable weakObjectsHashTable];
_delegateQueue = dispatch_get_main_queue();
_requests = [NSMutableArray new];
}

_requestResponseHandlerDelegate = requestResponseHandlerDelegate;

_cancellationTokens = [NSHashTable weakObjectsHashTable];
_delegateQueue = dispatch_get_main_queue();
_requests = [NSMutableArray new];

return self;
}

Expand All @@ -70,7 +68,7 @@ - (void)executeDelegateBlock:(dispatch_block_t)block

#pragma mark SPTDataLoader

- (id<SPTDataLoaderCancellationToken>)performRequest:(SPTDataLoaderRequest *)request
- (nullable id<SPTDataLoaderCancellationToken>)performRequest:(SPTDataLoaderRequest *)request
{
SPTDataLoaderRequest *copiedRequest = [request copy];
id<SPTDataLoaderDelegate> delegate = self.delegate;
Expand Down
9 changes: 4 additions & 5 deletions SPTDataLoader/SPTDataLoaderCancellationTokenImplementation.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,12 @@ + (instancetype)cancellationTokenImplementationWithDelegate:(id<SPTDataLoaderCan

- (instancetype)initWithDelegate:(id<SPTDataLoaderCancellationTokenDelegate>)delegate cancelObject:(nullable id)cancelObject
{
if (!(self = [super init])) {
return nil;
self = [super init];
if (self) {
_delegate = delegate;
_objectToCancel = cancelObject;
}

_delegate = delegate;
_objectToCancel = cancelObject;

return self;
}

Expand Down
21 changes: 10 additions & 11 deletions SPTDataLoader/SPTDataLoaderFactory.m
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,17 @@ + (instancetype)dataLoaderFactoryWithRequestResponseHandlerDelegate:(nullable id
- (instancetype)initWithRequestResponseHandlerDelegate:(nullable id<SPTDataLoaderRequestResponseHandlerDelegate>)requestResponseHandlerDelegate
authorisers:(nullable NSArray<id<SPTDataLoaderAuthoriser>> *)authorisers
{
if (!(self = [super init])) {
return nil;
}

_requestResponseHandlerDelegate = requestResponseHandlerDelegate;
_authorisers = [authorisers copy];

_requestToRequestResponseHandler = [NSMapTable weakToWeakObjectsMapTable];
_requestTimeoutQueue = dispatch_get_main_queue();
self = [super init];
if (self) {
_requestResponseHandlerDelegate = requestResponseHandlerDelegate;
_authorisers = [authorisers copy];

for (id<SPTDataLoaderAuthoriser> authoriser in _authorisers) {
authoriser.delegate = self;
_requestToRequestResponseHandler = [NSMapTable weakToWeakObjectsMapTable];
_requestTimeoutQueue = dispatch_get_main_queue();

for (id<SPTDataLoaderAuthoriser> authoriser in _authorisers) {
authoriser.delegate = self;
}
}

return self;
Expand Down
17 changes: 6 additions & 11 deletions SPTDataLoader/SPTDataLoaderRateLimiter.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,14 @@ + (instancetype)rateLimiterWithDefaultRequestsPerSecond:(double)requestsPerSecon

- (instancetype)initWithDefaultRequestsPerSecond:(double)requestsPerSecond
{
if (!(self = [super init])) {
return nil;
self = [super init];
if (self) {
_requestsPerSecond = requestsPerSecond;
_serviceEndpointRequestsPerSecond = [NSMutableDictionary new];
_serviceEndpointLastExecution = [NSMutableDictionary new];
_serviceEndpointRetryAt = [NSMutableDictionary new];
}

_requestsPerSecond = requestsPerSecond;
_serviceEndpointRequestsPerSecond = [NSMutableDictionary new];
_serviceEndpointLastExecution = [NSMutableDictionary new];
_serviceEndpointRetryAt = [NSMutableDictionary new];

return self;
}

Expand Down Expand Up @@ -135,10 +134,6 @@ - (double)requestsPerSecondForServiceKey:(NSString *)serviceKey

- (NSString *)serviceKeyFromURL:(NSURL *)URL
{
if (!URL) {
return nil;
}

NSURLComponents *requestComponents = [NSURLComponents componentsWithURL:URL resolvingAgainstBaseURL:NO];
NSURLComponents *serviceComponents = [NSURLComponents new];
serviceComponents.scheme = requestComponents.scheme;
Expand Down
21 changes: 10 additions & 11 deletions SPTDataLoader/SPTDataLoaderRequest.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,16 @@ - (instancetype)initWithURL:(NSURL *)URL sourceIdentifier:(nullable NSString *)s
{
static int64_t uniqueIdentifierBarrier = 0;

if (!(self = [super init])) {
return nil;
}

_URL = URL;
_sourceIdentifier = sourceIdentifier;

_mutableHeaders = [NSMutableDictionary new];
_method = SPTDataLoaderRequestMethodGet;
@synchronized(self.class) {
_uniqueIdentifier = uniqueIdentifierBarrier++;
self = [super init];
if (self) {
_URL = URL;
_sourceIdentifier = sourceIdentifier;

_mutableHeaders = [NSMutableDictionary new];
_method = SPTDataLoaderRequestMethodGet;
@synchronized(self.class) {
_uniqueIdentifier = uniqueIdentifierBarrier++;
}
}

return self;
Expand Down
3 changes: 2 additions & 1 deletion SPTDataLoader/SPTDataLoaderRequestTaskHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ NS_ASSUME_NONNULL_BEGIN
/**
* Tell the operation the URL session has completed the request
* @param error An optional error to use if the request was not completed successfully
* @return The response object unless the request was cancelled or will be re-tried in which case `nil` is returned.
*/
- (SPTDataLoaderResponse *)completeWithError:(nullable NSError *)error;
- (nullable SPTDataLoaderResponse *)completeWithError:(nullable NSError *)error;
/**
* Gets called whenever the original request was redirected.
* Returns YES to allow redirect, NO to block it.
Expand Down
33 changes: 16 additions & 17 deletions SPTDataLoader/SPTDataLoaderRequestTaskHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -77,24 +77,23 @@ - (instancetype)initWithTask:(NSURLSessionTask *)task
{
const NSTimeInterval SPTDataLoaderRequestTaskHandlerMaximumTime = 60.0;
const NSTimeInterval SPTDataLoaderRequestTaskHandlerInitialTime = 1.0;

if (!(self = [super init])) {
return nil;

self = [super init];
if (self) {
_task = task;
_request = request;
_requestResponseHandler = requestResponseHandler;
_rateLimiter = rateLimiter;

__weak __typeof(self) weakSelf = self;
_executionBlock = ^{
[weakSelf checkRateLimiterAndExecute];
};
_exponentialTimer = [SPTDataLoaderExponentialTimer exponentialTimerWithInitialTime:SPTDataLoaderRequestTaskHandlerInitialTime
maxTime:SPTDataLoaderRequestTaskHandlerMaximumTime];
_retryQueue = dispatch_get_main_queue();
}

_task = task;
_request = request;
_requestResponseHandler = requestResponseHandler;
_rateLimiter = rateLimiter;

__weak __typeof(self) weakSelf = self;
_executionBlock = ^ {
[weakSelf checkRateLimiterAndExecute];
};
_exponentialTimer = [SPTDataLoaderExponentialTimer exponentialTimerWithInitialTime:SPTDataLoaderRequestTaskHandlerInitialTime
maxTime:SPTDataLoaderRequestTaskHandlerMaximumTime];
_retryQueue = dispatch_get_main_queue();

return self;
}

Expand All @@ -112,7 +111,7 @@ - (void)receiveData:(NSData *)data
}];
}

- (SPTDataLoaderResponse *)completeWithError:(nullable NSError *)error
- (nullable SPTDataLoaderResponse *)completeWithError:(nullable NSError *)error
{
id<SPTDataLoaderRequestResponseHandler> requestResponseHandler = self.requestResponseHandler;
if (!self.response) {
Expand Down
14 changes: 6 additions & 8 deletions SPTDataLoader/SPTDataLoaderResolverAddress.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@

@interface SPTDataLoaderResolverAddress ()

@property (nonatomic, assign) NSTimeInterval stalePeriod;

@property (nonatomic, assign, readonly) NSTimeInterval stalePeriod;
@property (nonatomic, assign) CFAbsoluteTime lastFailedTime;

@end
Expand Down Expand Up @@ -53,14 +52,13 @@ + (instancetype)dataLoaderResolverAddressWithAddress:(NSString *)address
- (instancetype)initWithAddress:(NSString *)address
{
const NSTimeInterval SPTDataLoaderResolverAddressDefaultStalePeriodOneHour = 60.0 * 60.0;

if (!(self = [super init])) {
return nil;

self = [super init];
if (self) {
_address = address;
_stalePeriod = SPTDataLoaderResolverAddressDefaultStalePeriodOneHour;
}

_address = address;
_stalePeriod = SPTDataLoaderResolverAddressDefaultStalePeriodOneHour;

return self;
}

Expand Down
35 changes: 17 additions & 18 deletions SPTDataLoader/SPTDataLoaderResponse.m
Original file line number Diff line number Diff line change
Expand Up @@ -49,27 +49,26 @@ + (instancetype)dataLoaderResponseWithRequest:(SPTDataLoaderRequest *)request re

- (instancetype)initWithRequest:(SPTDataLoaderRequest *)request response:(nullable NSURLResponse *)response
{
if (!(self = [super init])) {
return nil;
}

_request = request;
_response = response;

if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode >= SPTDataLoaderResponseHTTPStatusCodeMovedMultipleChoices
|| httpResponse.statusCode <= SPTDataLoaderResponseHTTPStatusCodeSwitchProtocols) {
_error = [NSError errorWithDomain:SPTDataLoaderResponseErrorDomain
code:httpResponse.statusCode
userInfo:nil];
self = [super init];
if (self) {
_request = request;
_response = response;

if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode >= SPTDataLoaderResponseHTTPStatusCodeMovedMultipleChoices
|| httpResponse.statusCode <= SPTDataLoaderResponseHTTPStatusCodeSwitchProtocols) {
_error = [NSError errorWithDomain:SPTDataLoaderResponseErrorDomain
code:httpResponse.statusCode
userInfo:nil];
}
_responseHeaders = httpResponse.allHeaderFields;
_statusCode = httpResponse.statusCode;
}
_responseHeaders = httpResponse.allHeaderFields;
_statusCode = httpResponse.statusCode;

_retryAfter = [self retryAfterForHeaders:_responseHeaders];
}

_retryAfter = [self retryAfterForHeaders:_responseHeaders];

return self;
}

Expand Down
47 changes: 23 additions & 24 deletions SPTDataLoader/SPTDataLoaderService.m
Original file line number Diff line number Diff line change
Expand Up @@ -70,31 +70,30 @@ - (instancetype)initWithUserAgent:(NSString *)userAgent
const NSUInteger SPTDataLoaderServiceMaxConcurrentOperations = 32;

NSString * const SPTDataLoaderServiceUserAgentHeader = @"User-Agent";

if (!(self = [super init])) {
return nil;
}

_rateLimiter = rateLimiter;
_resolver = resolver;

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.timeoutIntervalForRequest = SPTDataLoaderServiceTimeoutInterval;
configuration.timeoutIntervalForResource = SPTDataLoaderServiceTimeoutInterval;
configuration.HTTPShouldUsePipelining = YES;
configuration.protocolClasses = customURLProtocolClasses;
if (userAgent) {
configuration.HTTPAdditionalHeaders = @{ SPTDataLoaderServiceUserAgentHeader : userAgent };

self = [super init];
if (self) {
_rateLimiter = rateLimiter;
_resolver = resolver;

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.timeoutIntervalForRequest = SPTDataLoaderServiceTimeoutInterval;
configuration.timeoutIntervalForResource = SPTDataLoaderServiceTimeoutInterval;
configuration.HTTPShouldUsePipelining = YES;
configuration.protocolClasses = customURLProtocolClasses;
if (userAgent) {
configuration.HTTPAdditionalHeaders = @{ SPTDataLoaderServiceUserAgentHeader : userAgent };
}

_cancellationTokenFactory = [SPTDataLoaderCancellationTokenFactoryImplementation new];
_sessionQueue = [NSOperationQueue new];
_sessionQueue.maxConcurrentOperationCount = SPTDataLoaderServiceMaxConcurrentOperations;
_sessionQueue.name = NSStringFromClass(self.class);
_session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:_sessionQueue];
_handlers = [NSMutableArray new];
_consumptionObservers = [NSMapTable weakToStrongObjectsMapTable];
}

_cancellationTokenFactory = [SPTDataLoaderCancellationTokenFactoryImplementation new];
_sessionQueue = [NSOperationQueue new];
_sessionQueue.maxConcurrentOperationCount = SPTDataLoaderServiceMaxConcurrentOperations;
_sessionQueue.name = NSStringFromClass(self.class);
_session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:_sessionQueue];
_handlers = [NSMutableArray new];
_consumptionObservers = [NSMapTable weakToStrongObjectsMapTable];

return self;
}

Expand All @@ -121,7 +120,7 @@ - (void)removeConsumptionObserver:(id<SPTDataLoaderConsumptionObserver>)consumpt
}
}

- (SPTDataLoaderRequestTaskHandler *)handlerForTask:(NSURLSessionTask *)task
- (nullable SPTDataLoaderRequestTaskHandler *)handlerForTask:(NSURLSessionTask *)task
{
NSArray *handlers = nil;
@synchronized(self.handlers) {
Expand Down
21 changes: 16 additions & 5 deletions include/SPTDataLoader/SPTDataLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,32 @@ NS_ASSUME_NONNULL_BEGIN
*/
@interface SPTDataLoader : NSObject

#pragma mark Delegating Tasks

/**
* The object listening to the data loader
* The object listening to the data loader.
*/
@property (nonatomic, weak, nullable) id<SPTDataLoaderDelegate> delegate;
/**
* The queue to call the delegate selectors on
* @discussion By default this is the main queue
* The queue to call the delegate selectors on.
* @discussion By default this is the main queue.
*/
@property (nonatomic, strong) dispatch_queue_t delegateQueue;

#pragma mark Performing Requests

/**
* Performs a request
* Performs a request and returns a cancellation token associated with it.
* @discussion If the request can’t be performed `nil` will be returned and the receiver’s delegate will be sent the
* `dataLoader:didReceiveErrorResponse:`. The response object sent to the delegate will contain an `NSError` object
* describing what went wrong.
* @param request The object describing the kind of request to be performed
* @return A cancellation token associated with the request, or `nil` if the request coulnd’t be performed.
*/
- (id<SPTDataLoaderCancellationToken>)performRequest:(SPTDataLoaderRequest *)request;
- (nullable id<SPTDataLoaderCancellationToken>)performRequest:(SPTDataLoaderRequest *)request;

#pragma mark Cancelling Loads

/**
* Cancels all the currently operating and pending requests
*/
Expand Down

0 comments on commit 17b1660

Please sign in to comment.