Introduce a new heuristic based approach for determining if a response can skip the mapping process. Also introduces a new Network + CoreData logging component and reduces the chattiness of the debug logging level for Core Data Network events.

This commit is contained in:
Blake Watters
2013-03-07 19:25:01 -05:00
parent 02247695b1
commit a9ef1fe39d
4 changed files with 48 additions and 7 deletions

View File

@@ -35,13 +35,12 @@
// Set Logging Component
#undef RKLogComponent
#define RKLogComponent RKlcl_cRestKitCoreData
#define RKLogComponent RKlcl_cRestKitNetworkCoreData
@interface RKEntityMappingEvent : NSObject
@property (nonatomic, copy) id rootKey;
@property (nonatomic, copy) NSString *keyPath;
@property (nonatomic, strong) RKEntityMapping *entityMapping;
@property (nonatomic, readonly) BOOL canSkipMapping;
+ (instancetype)eventWithRootKey:(id)rootKey keyPath:(NSString *)keyPath entityMapping:(RKEntityMapping *)entityMapping;
@end
@@ -299,6 +298,8 @@ static NSURL *RKRelativeURLFromURLAndResponseDescriptors(NSURL *URL, NSArray *re
@property (nonatomic, strong, readwrite) RKMappingResult *mappingResult;
@property (nonatomic, copy) id (^willMapDeserializedResponseBlock)(id deserializedResponseBody);
@property (nonatomic, strong) NSArray *entityMappingEvents;
@property (nonatomic, strong) NSCachedURLResponse *cachedResponse;
@end
@implementation RKManagedObjectRequestOperation
@@ -312,6 +313,7 @@ static NSURL *RKRelativeURLFromURLAndResponseDescriptors(NSURL *URL, NSArray *re
if (self) {
self.savesToPersistentStore = YES;
self.deletesOrphanedObjects = YES;
self.cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:requestOperation.request];
}
return self;
}
@@ -372,14 +374,31 @@ static NSURL *RKRelativeURLFromURLAndResponseDescriptors(NSURL *URL, NSArray *re
// RKResponseHasBeenMappedCacheUserInfoKey is stored by RKObjectRequestOperation
- (BOOL)canSkipMapping
{
NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:self.HTTPRequestOperation.request];
// Is the request cacheable
if (!self.cachedResponse) return NO;
NSURLRequest *request = self.HTTPRequestOperation.request;
if (! [[request HTTPMethod] isEqualToString:@"GET"] && ! [[request HTTPMethod] isEqualToString:@"HEAD"]) return NO;
NSHTTPURLResponse *response = (NSHTTPURLResponse *)self.HTTPRequestOperation.response;
if (! [RKCacheableStatusCodes() containsIndex:response.statusCode]) return NO;
// Check for a change in the Etag
NSString *cachedEtag = [[(NSHTTPURLResponse *)[self.cachedResponse response] allHeaderFields] objectForKey:@"Etag"];
NSString *responseEtag = [[response allHeaderFields] objectForKey:@"Etag"];
if (! [cachedEtag isEqualToString:responseEtag]) return NO;
// Response data has changed
NSData *responseData = self.HTTPRequestOperation.responseData;
if (! [responseData isEqualToData:[self.cachedResponse data]]) return NO;
// Check that we have mapped this response previously
NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
return [[cachedResponse.userInfo objectForKey:RKResponseHasBeenMappedCacheUserInfoKey] boolValue];
}
- (RKMappingResult *)performMappingOnResponse:(NSError **)error
{
if (self.canSkipMapping) {
RKLogDebug(@"Managed object mapping requested for cached response: skipping mapping...");
if ([self canSkipMapping]) {
RKLogDebug(@"Managed object mapping requested for cached response which was previously mapped: skipping...");
NSURL *URL = RKRelativeURLFromURLAndResponseDescriptors(self.HTTPRequestOperation.response.URL, self.responseDescriptors);
NSArray *fetchRequests = RKArrayOfFetchRequestFromBlocksWithURL(self.fetchRequestBlocks, URL);
NSMutableArray *managedObjects = [NSMutableArray array];
@@ -470,7 +489,7 @@ static NSURL *RKRelativeURLFromURLAndResponseDescriptors(NSURL *URL, NSArray *re
RKLogTrace(@"Fetched local objects matching URL '%@' with fetch request '%@': %@", URL, fetchRequest, _blockObjects);
[localObjects addObjectsFromArray:_blockObjects];
} else {
RKLogDebug(@"Fetch request block %@ returned nil fetch request for URL: '%@'", fetchRequestBlock, URL);
RKLogTrace(@"Fetch request block %@ returned nil fetch request for URL: '%@'", fetchRequestBlock, URL);
}
}
@@ -489,7 +508,7 @@ static NSURL *RKRelativeURLFromURLAndResponseDescriptors(NSURL *URL, NSArray *re
return YES;
}
if (self.canSkipMapping) {
if ([self canSkipMapping]) {
RKLogDebug(@"Skipping deletion of orphaned objects: 304 (Not Modified) status code encountered");
return YES;
}