Skip to content
This repository has been archived by the owner on Feb 29, 2020. It is now read-only.

Commit

Permalink
[iOS] Add support for configuring page size of a pull operation
Browse files Browse the repository at this point in the history
  • Loading branch information
shrishrirang committed Jun 11, 2015
1 parent 84fb0c2 commit 0c31aa3
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 7 deletions.
8 changes: 8 additions & 0 deletions sdk/iOS/WindowsAzureMobileServices.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@
CF762EC91A1D37A40018C292 /* MSDateOffset.m in Sources */ = {isa = PBXBuildFile; fileRef = CF762EC71A1D36950018C292 /* MSDateOffset.m */; };
CFAE6E0A1A3B84D700734128 /* MSTableConfigValue.m in Sources */ = {isa = PBXBuildFile; fileRef = CFAE6E091A3B84D700734128 /* MSTableConfigValue.m */; };
CFAE6E0C1A3B84E400734128 /* MSTableConfigValue.h in Headers */ = {isa = PBXBuildFile; fileRef = CFAE6E0B1A3B84E400734128 /* MSTableConfigValue.h */; };
D0D3B9361B290D80002A126A /* MSPullSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = D0D3B9351B290D80002A126A /* MSPullSettings.m */; };
D0D3B9371B2A267F002A126A /* MSPullSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = D0D3B9341B2906EF002A126A /* MSPullSettings.h */; settings = {ATTRIBUTES = (Public, ); }; };
E8146642165BE0150038EBE5 /* MSLogin.h in Headers */ = {isa = PBXBuildFile; fileRef = E8146640165BE0150038EBE5 /* MSLogin.h */; };
E8146643165BE0150038EBE5 /* MSLogin.m in Sources */ = {isa = PBXBuildFile; fileRef = E8146641165BE0150038EBE5 /* MSLogin.m */; };
E8146646165BE2440038EBE5 /* MSLoginSerializer.h in Headers */ = {isa = PBXBuildFile; fileRef = E8146644165BE2440038EBE5 /* MSLoginSerializer.h */; };
Expand Down Expand Up @@ -241,6 +243,8 @@
CF762EC71A1D36950018C292 /* MSDateOffset.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSDateOffset.m; sourceTree = "<group>"; };
CFAE6E091A3B84D700734128 /* MSTableConfigValue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSTableConfigValue.m; sourceTree = "<group>"; };
CFAE6E0B1A3B84E400734128 /* MSTableConfigValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSTableConfigValue.h; sourceTree = "<group>"; };
D0D3B9341B2906EF002A126A /* MSPullSettings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSPullSettings.h; sourceTree = "<group>"; };
D0D3B9351B290D80002A126A /* MSPullSettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSPullSettings.m; sourceTree = "<group>"; };
E8146640165BE0150038EBE5 /* MSLogin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSLogin.h; sourceTree = "<group>"; };
E8146641165BE0150038EBE5 /* MSLogin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSLogin.m; sourceTree = "<group>"; };
E8146644165BE2440038EBE5 /* MSLoginSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSLoginSerializer.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -359,6 +363,8 @@
isa = PBXGroup;
children = (
A2ACD539192322760012B1ED /* CoreData */,
D0D3B9341B2906EF002A126A /* MSPullSettings.h */,
D0D3B9351B290D80002A126A /* MSPullSettings.m */,
A2C14C6819105D9F00A58609 /* MSSyncContextReadResult.h */,
A2C14C6919105D9F00A58609 /* MSSyncContextReadResult.m */,
A258890718A19D0B00962F9A /* MSSyncTable.h */,
Expand Down Expand Up @@ -667,6 +673,7 @@
A258891618A19D0B00962F9A /* MSSyncTable.h in Headers */,
E8E37912161F769D00C13F00 /* MSUser.h in Headers */,
A258891418A19D0B00962F9A /* MSSyncContext.h in Headers */,
D0D3B9371B2A267F002A126A /* MSPullSettings.h in Headers */,
A281900418BB2FF5001B14E7 /* MSTableOperationError.h in Headers */,
E8E37913161F769D00C13F00 /* MSFilter.h in Headers */,
A2ACD540192322C50012B1ED /* MSCoreDataStore.h in Headers */,
Expand Down Expand Up @@ -844,6 +851,7 @@
CF762EC91A1D37A40018C292 /* MSDateOffset.m in Sources */,
E8F33B15161667CE002DD7C6 /* MSClient.m in Sources */,
A258890C18A19D0B00962F9A /* MSOperationQueue.m in Sources */,
D0D3B9361B290D80002A126A /* MSPullSettings.m in Sources */,
E8F33B16161667CE002DD7C6 /* MSError.m in Sources */,
7929542919B7C793006A3829 /* MSQueryResult.m in Sources */,
E8F33B17161667CE002DD7C6 /* MSQuery.m in Sources */,
Expand Down
29 changes: 29 additions & 0 deletions sdk/iOS/src/MSPullSettings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// ----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------

#import <Foundation/Foundation.h>

/// Settings that control the pull behavior
@interface MSPullSettings : NSObject

#pragma mark * Properties

///@name Properties that control pull behavior
///@{

/// Size of pages requested from the server while performing a pull
@property (nonatomic) NSInteger pageSize;

///@}

#pragma mark * Class methods

///@name Class factory methods

/// Class factory method for getting default pull settings
+ (MSPullSettings *)default;

///}

@end
44 changes: 44 additions & 0 deletions sdk/iOS/src/MSPullSettings.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// ----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------

#import "MSPullSettings.h"

#pragma mark * MSPullSettings Implementation

@implementation MSPullSettings

NSInteger const defaultPageSize = 50;

@synthesize pageSize = _pageSize;

#pragma mark * Initializer method(s)

- (id)init {
self = [super init];
if (self) {
_pageSize = defaultPageSize;
}

return self;
}

#pragma mark * Accessor method(s)

- (void)setPageSize:(NSInteger)pageSize {
if (pageSize <= 0) {
_pageSize = defaultPageSize;
}
else {
_pageSize = pageSize;
}
}

#pragma mark * Class factory method(s)

+ (MSPullSettings *)default {
return [MSPullSettings new];
}

@end

18 changes: 13 additions & 5 deletions sdk/iOS/src/MSSyncContext.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ @implementation MSSyncContext {
dispatch_queue_t writeOperationQueue;
}

NSInteger const defaultFetchLimit = 50;

static NSOperationQueue *pushQueue_;

@synthesize delegate = delegate_;
Expand Down Expand Up @@ -322,12 +320,22 @@ - (void) cancelOperation:(MSTableOperation *)operation discardItemWithCompletion
});
}

/// Verify our input is valid and try to pull our data down from the server
/// Pull data down from the server
- (NSOperation *) pullWithQuery:(MSQuery *)query queryId:(NSString *)queryId completion:(MSSyncBlock)completion;
{
return [self pullWithQuery:query queryId:queryId pullSettings:nil completion:completion];
}

/// Verify our input is valid and try to pull our data down from the server
- (NSOperation *) pullWithQuery:(MSQuery *)query queryId:(NSString *)queryId pullSettings:(MSPullSettings *)pullSettings completion:(MSSyncBlock)completion;
{
// make a copy since we'll be modifying it internally
MSQuery *queryCopy = [query copy];

if (!pullSettings) {
pullSettings = [MSPullSettings default];
}

// We want to throw on unsupported fields so we can change this decision later
NSError *error;
NSDictionary *isDeletedParams = [MSSyncContext dictionary:queryCopy.parameters entriesForCaseInsensitiveKey:@"__includedeleted"];
Expand Down Expand Up @@ -401,9 +409,9 @@ - (NSOperation *) pullWithQuery:(MSQuery *)query queryId:(NSString *)queryId com
}

// For a Pull we treat fetchLimit as the total records we should pull by paging. If there is no fetchLimit, we pull everything.
// We enforce a page size of 50.
// We enforce a page size of |pullSettings.pageSize|
NSInteger maxRecords = query.fetchLimit >= 0 ? query.fetchLimit : NSIntegerMax;
queryCopy.fetchLimit = MIN(maxRecords, defaultFetchLimit);
queryCopy.fetchLimit = MIN(maxRecords, pullSettings.pageSize);

// Begin the actual pull request
return [self pullWithQueryInternal:queryCopy queryId:queryId maxRecords:maxRecords completion:completion];
Expand Down
3 changes: 3 additions & 0 deletions sdk/iOS/src/MSSyncContextInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#import "MSClient.h"
#import "MSOperationQueue.h"
#import "MSTable.h"
#import "MSPullSettings.h"

@interface MSSyncContext()

Expand All @@ -27,6 +28,8 @@

-(NSOperation *) pullWithQuery:(MSQuery *)query queryId:(NSString *)queryId completion:(MSSyncBlock)completion;

-(NSOperation *) pullWithQuery:(MSQuery *)query queryId:(NSString *)queryId pullSettings:(MSPullSettings *)pullSettings completion:(MSSyncBlock)completion;

-(NSOperation *) purgeWithQuery:(MSQuery *)query completion:(MSSyncBlock)completion;

-(NSOperation *) forcePurgeWithTable:(MSSyncTable *)syncTable completion:(MSSyncBlock)completion;
Expand Down
10 changes: 9 additions & 1 deletion sdk/iOS/src/MSSyncTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#import <Foundation/Foundation.h>
#import "MSClient.h"
#import "MSTable.h"
#import "MSPullSettings.h"

@class MSQueuePullOperation;
@class MSQueuePurgeOperation;
Expand Down Expand Up @@ -96,12 +97,19 @@
/// @{

/// Initiates a request to go to the server and get a set of records matching the specified
/// MSQeury object.
/// MSQuery object.
/// Before a pull is allowed to run, one operation to send all pending requests on the
/// specified table will be sent to the server. If a pending request for this table fails,
/// the pull will be cancelled
-(NSOperation *)pullWithQuery:(MSQuery *)query queryId:(NSString *)queryId completion:(MSSyncBlock)completion;

/// Initiates a request to go to the server and get a set of records matching the specified
/// MSQuery object.
/// Before a pull is allowed to run, one operation to send all pending requests on the
/// specified table will be sent to the server. If a pending request for this table fails,
/// the pull will be cancelled
-(NSOperation *)pullWithQuery:(MSQuery *)query queryId:(NSString *)queryId pullSettings:(MSPullSettings *)pullSettings completion:(MSSyncBlock)completion;

/// Removes all records in the local cache that match the results of the specified query.
/// If query is nil, all records in the local table will be removed.
/// Before local data is removed, a check will be made for pending operations on this table. If
Expand Down
7 changes: 6 additions & 1 deletion sdk/iOS/src/MSSyncTable.m
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ -(void)delete:(NSDictionary *)item completion:(MSSyncBlock)completion

-(NSOperation *)pullWithQuery:(MSQuery *)query queryId:(NSString *)queryId completion:(MSSyncBlock)completion
{
return [self.client.syncContext pullWithQuery:query queryId:queryId completion:completion];
return [self pullWithQuery:query queryId:queryId pullSettings:nil completion:completion];
}

-(NSOperation *)pullWithQuery:(MSQuery *)query queryId:(NSString *)queryId pullSettings:(id)pullSettings completion:(MSSyncBlock)completion
{
return [self.client.syncContext pullWithQuery:query queryId:queryId pullSettings:pullSettings completion:completion];
}

-(NSOperation *)purgeWithQuery:(MSQuery *)query completion:(MSSyncBlock)completion
Expand Down
136 changes: 136 additions & 0 deletions sdk/iOS/test/MSSyncTableTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -1584,6 +1584,142 @@ -(void) testPullWithFetchLimitNotMultipleOfFifty
@"Invalid URL: %@", thirdRequest.URL.absoluteString);
}

-(void) testPullTable_UsePullSettings_NegativePageSize
{
MSPullSettings *pullSettings = [MSPullSettings new];
pullSettings.pageSize = -1;

NSString *pullRequest = [self getPullTableRequestWithPullSettings:pullSettings usePullSettings:YES];

XCTAssertEqualObjects(pullRequest, @"https://someUrl/tables/TodoNoVersion?$top=50&__includeDeleted=true&$skip=0&__systemProperties=__deleted", "Incorrect pull request");
}

-(void) testPullTable_UsePullSettings_ZeroPageSize
{
MSPullSettings *pullSettings = [MSPullSettings new];
pullSettings.pageSize = 0;

NSString *pullRequest = [self getPullTableRequestWithPullSettings:pullSettings usePullSettings:YES];

XCTAssertEqualObjects(pullRequest, @"https://someUrl/tables/TodoNoVersion?$top=50&__includeDeleted=true&$skip=0&__systemProperties=__deleted", "Incorrect pull request");
}

-(void) testPullTable_UsePullSettings_ValidPageSize
{
MSPullSettings *pullSettings = [MSPullSettings new];
pullSettings.pageSize = 1;

NSString *pullRequest = [self getPullTableRequestWithPullSettings:pullSettings usePullSettings:YES];

XCTAssertEqualObjects(pullRequest, @"https://someUrl/tables/TodoNoVersion?$top=1&__includeDeleted=true&$skip=0&__systemProperties=__deleted", "Incorrect pull request");
}

-(void) testPullTable_PageOptionsNil
{
NSString *pullRequest = [self getPullTableRequestWithPullSettings:nil usePullSettings:YES];

XCTAssertEqualObjects(pullRequest, @"https://someUrl/tables/TodoNoVersion?$top=50&__includeDeleted=true&$skip=0&__systemProperties=__deleted", "Incorrect pull request");
}

-(void) testPullTable_NoPageOptions
{
NSString *pullRequest = [self getPullTableRequestWithPullSettings:nil usePullSettings:NO];

XCTAssertEqualObjects(pullRequest, @"https://someUrl/tables/TodoNoVersion?$top=50&__includeDeleted=true&$skip=0&__systemProperties=__deleted", "Incorrect pull request");
}

-(NSString *) getPullTableRequestWithPullSettings:(MSPullSettings *)pullSettings usePullSettings:(BOOL)shouldUsePullSettings
{
MSTestFilter *testFilter = [MSTestFilter testFilterWithStatusCode:200 data:nil];
__block NSString *pullRequest = nil;

testFilter.onInspectRequest = ^(NSURLRequest *request) {
pullRequest = request.URL.absoluteString;
return request;
};

MSClient *filteredClient = [client clientWithFilter:testFilter];
MSSyncTable *todoTable = [filteredClient syncTableWithName:TodoTableNoVersion];
MSQuery *query = [[MSQuery alloc] initWithSyncTable:todoTable];

if (shouldUsePullSettings) {
[[todoTable pullWithQuery:query queryId:nil pullSettings:pullSettings completion:nil] waitUntilFinished];
}
else {
[[todoTable pullWithQuery:query queryId:nil completion:nil] waitUntilFinished];
}

return pullRequest;
}

-(void) testPullSyncContext_UsePullSettings_NegativePageSize
{
MSPullSettings *pullSettings = [MSPullSettings new];
pullSettings.pageSize = -1;

NSString *pullRequest = [self getPullSyncContextRequestWithPullSettings:pullSettings usePullSettings:YES];

XCTAssertEqualObjects(pullRequest, @"https://someUrl/tables/TodoNoVersion?$top=50&__includeDeleted=true&$skip=0&__systemProperties=__deleted", "Incorrect pull request");
}

-(void) testPullSyncContext_UsePullSettings_ZeroPageSize
{
MSPullSettings *pullSettings = [MSPullSettings new];
pullSettings.pageSize = 0;

NSString *pullRequest = [self getPullSyncContextRequestWithPullSettings:pullSettings usePullSettings:YES];

XCTAssertEqualObjects(pullRequest, @"https://someUrl/tables/TodoNoVersion?$top=50&__includeDeleted=true&$skip=0&__systemProperties=__deleted", "Incorrect pull request");
}

-(void) testPullSyncContext_UsePullSettings_ValidPageSize
{
MSPullSettings *pullSettings = [MSPullSettings new];
pullSettings.pageSize = 1;

NSString *pullRequest = [self getPullSyncContextRequestWithPullSettings:pullSettings usePullSettings:YES];

XCTAssertEqualObjects(pullRequest, @"https://someUrl/tables/TodoNoVersion?$top=1&__includeDeleted=true&$skip=0&__systemProperties=__deleted", "Incorrect pull request");
}

-(void) testPullSyncContext_PageOptionsNil
{
NSString *pullRequest = [self getPullSyncContextRequestWithPullSettings:nil usePullSettings:YES];

XCTAssertEqualObjects(pullRequest, @"https://someUrl/tables/TodoNoVersion?$top=50&__includeDeleted=true&$skip=0&__systemProperties=__deleted", "Incorrect pull request");
}

-(void) testPullSyncContext_NoPageOptions
{
NSString *pullRequest = [self getPullSyncContextRequestWithPullSettings:nil usePullSettings:NO];

XCTAssertEqualObjects(pullRequest, @"https://someUrl/tables/TodoNoVersion?$top=50&__includeDeleted=true&$skip=0&__systemProperties=__deleted", "Incorrect pull request");
}

-(NSString *) getPullSyncContextRequestWithPullSettings:(MSPullSettings *)pullSettings usePullSettings:(BOOL)shouldUsePullSettings
{
MSTestFilter *testFilter = [MSTestFilter testFilterWithStatusCode:200 data:nil];
__block NSString *pullRequest = nil;

testFilter.onInspectRequest = ^(NSURLRequest *request) {
pullRequest = request.URL.absoluteString;
return request;
};

MSClient *filteredClient = [client clientWithFilter:testFilter];
MSSyncTable *todoTable = [filteredClient syncTableWithName:TodoTableNoVersion];
MSQuery *query = [[MSQuery alloc] initWithSyncTable:todoTable];

if (shouldUsePullSettings) {
[[filteredClient.syncContext pullWithQuery:query queryId:nil pullSettings:pullSettings completion:nil] waitUntilFinished];
}
else {
[[filteredClient.syncContext pullWithQuery:query queryId:nil completion:nil] waitUntilFinished];
}

return pullRequest;
}

-(void) testPullWithFetchOffset
{
// Pull should start with a $skip and the skip should be incremented by the number of records pulled
Expand Down

0 comments on commit 0c31aa3

Please sign in to comment.