Skip to content

Consistency errors #1237

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 39 commits into from
Jan 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
73b6651
wip
flovilmart Jan 19, 2018
30ffc60
wip
flovilmart Jan 19, 2018
e755c23
Initial refactoring of Consistency Assertion to Consistency errors
flovilmart Jan 19, 2018
4526f07
Soft errors for User consistency checks `_checkSaveParametersWithCurr…
flovilmart Jan 19, 2018
816a6e2
Bumps to latest Swift
flovilmart Jan 19, 2018
1e049f3
Proper failable methods for the LocalIdStore
flovilmart Jan 19, 2018
88ef74f
Adds precondition for checking if user is not merging on itself
flovilmart Jan 20, 2018
3ab3546
Swallow consistency error when decoding
flovilmart Jan 20, 2018
e0ed31f
Base error checking on return parameters as unsafe to check error / *…
flovilmart Jan 20, 2018
2af299f
Restore behaviour for nil tranformed objects without errors
flovilmart Jan 20, 2018
bc95c30
proper ARC modifier for NSError**
flovilmart Jan 20, 2018
54a07f0
Transform assertions to errors in children collection
flovilmart Jan 20, 2018
c767855
Adds PFPrecondition instead of Exception when saving cycles
flovilmart Jan 20, 2018
30ec1f9
Properly bail on encoding errors, add tests
flovilmart Jan 20, 2018
bd3d622
nits: TODOs
flovilmart Jan 20, 2018
cb97ec5
Improve handling of failures for localId resolutiosn
flovilmart Jan 20, 2018
aa3f7c0
Report missing localId as soft errors
flovilmart Jan 20, 2018
34f3b8f
Refactor: Rename macros in PFPreconditon, more consistency on arguments
flovilmart Jan 20, 2018
5c3d70e
Better error propagation in resolving localIds
flovilmart Jan 20, 2018
32886fc
More tests for failures of localId resolutions
flovilmart Jan 20, 2018
e634afa
Bump version to 1.16.1-alpha.1
flovilmart Jan 20, 2018
00e3393
Bump podspec to 1.17.0-alpha.1
flovilmart Jan 20, 2018
9a237a1
Fix issue #916
flovilmart Jan 21, 2018
c6660c2
Fixes #1184
flovilmart Jan 21, 2018
e88222c
Adds r/w accessors in swift for the PFACL
flovilmart Jan 21, 2018
59e7cc0
Adds CHANGELOG.md
flovilmart Jan 21, 2018
1855401
Bumps to 1.17.0-alpha.2
flovilmart Jan 21, 2018
3a71d2f
Fixes flaky test
flovilmart Jan 21, 2018
7337f36
Provide more context when asserting OfflineStore objectId assignment …
flovilmart Jan 21, 2018
a4ed6b7
Bolts doesnt infer failed tasks with NSError as a return type, always…
flovilmart Jan 21, 2018
b1addae
Bump to 1.17.0-alpha.3
flovilmart Jan 22, 2018
20b8ddd
Releases on travis
flovilmart Jan 23, 2018
5d296a1
run pod trunk push with verbose to not stall travis
flovilmart Jan 23, 2018
155f30b
Review nits
flovilmart Jan 24, 2018
ea2fa1a
Do no track dimensions if they are nil
flovilmart Jan 24, 2018
8a03368
Bump version to 1.17.0-alpha.4
flovilmart Jan 24, 2018
278ab82
Adds precondition to prevent crash
flovilmart Jan 29, 2018
6ede892
Fixes errors
flovilmart Jan 30, 2018
190bfc1
Bumps to 1.17.0-alpha.5
flovilmart Jan 30, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
- run: *prepare
- run: |
xcrun simctl create "Apple TV 1080p" com.apple.CoreSimulator.SimDeviceType.Apple-TV-1080p com.apple.CoreSimulator.SimRuntime.tvOS-11-0
bundle exec rake test:deployment
bundle exec rake package:release
jazzy:
<<: *defaults
steps:
Expand Down
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ jobs:
- xcrun simctl create "Apple TV 1080p" com.apple.CoreSimulator.SimDeviceType.Apple-TV-1080p com.apple.CoreSimulator.SimRuntime.tvOS-11-2
- bundle exec rake test:deployment
- ./Scripts/jazzy.sh
- xcrun simctl create "Apple TV 1080p" com.apple.CoreSimulator.SimDeviceType.Apple-TV-1080p com.apple.CoreSimulator.SimRuntime.tvOS-11-0
- bundle exec rake package:release
deploy:
- provider: releases
api_key:
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Parse-SDK-iOS-OSX Chnagelog

### master

* Fixes NSInternalInconsistencyException handling starting Bolts 1.9.0 by emitting soft NSErrors
* Fixes issue affecting public getter/setters in PFACL's in Swift (#1083)
* Prevent deadlocks when saving objects with cicrular references (#916)
* Prevent deadlocks when running fetchAll with circluar references (#1184)
* Adds NSNotification when an invalid session token is encountered

1 change: 0 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ gem 'xcpretty'
gem 'xcodeproj'
gem 'cocoapods'
gem 'jazzy', '~> 0.9.0'

2 changes: 1 addition & 1 deletion Parse.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'Parse'
s.version = '1.16.0'
s.version = '1.17.0-alpha.5'
s.license = { :type => 'BSD', :file => 'LICENSE' }
s.homepage = 'http://parseplatform.org/'
s.summary = 'A library that gives you access to the powerful Parse cloud platform from your iOS/OS X/watchOS/tvOS app.'
Expand Down
5 changes: 5 additions & 0 deletions Parse/Parse.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -6826,6 +6826,9 @@
LastSwiftMigration = 0900;
TestTargetID = 4AE33A0A1F5451AD0088DCA0;
};
81C09F501AF97A490043B49C = {
LastSwiftMigration = 0920;
};
81C3821B19CCA89E0066284A = {
CreatedOnToolsVersion = 6.0.1;
LastSwiftMigration = 0830;
Expand Down Expand Up @@ -8588,13 +8591,15 @@
isa = XCBuildConfiguration;
baseConfigurationReference = F55ABB5A1B4F39DA00A0ECD5 /* ParseUnitTests-macOS.xcconfig */;
buildSettings = {
SWIFT_VERSION = 4.0;
};
name = Debug;
};
81C09F851AF97A490043B49C /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = F55ABB5A1B4F39DA00A0ECD5 /* ParseUnitTests-macOS.xcconfig */;
buildSettings = {
SWIFT_VERSION = 4.0;
};
name = Release;
};
Expand Down
2 changes: 1 addition & 1 deletion Parse/Parse/Internal/ACL/PFACLPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
/*
Gets the encoded format for an ACL.
*/
- (NSDictionary *)encodeIntoDictionary;
- (NSDictionary *)encodeIntoDictionary:(NSError **)error;

/*
Creates a new ACL object from an existing dictionary.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,11 @@ + (instancetype)controllerWithDataSource:(id<PFEventuallyQueueProvider>)dataSour
@weakify(self);
return [[BFTask taskFromExecutor:[BFExecutor defaultPriorityBackgroundExecutor] withBlock:^id{
@strongify(self);
NSDictionary *encodedDimensions = [[PFNoObjectEncoder objectEncoder] encodeObject:dimensions];
NSError *error;
NSDictionary *encodedDimensions = [[PFNoObjectEncoder objectEncoder] encodeObject:dimensions error:&error];
if (encodedDimensions == nil) {
return [BFTask taskWithError:error];
}
PFRESTCommand *command = [PFRESTAnalyticsCommand trackEventCommandWithEventName:name
dimensions:encodedDimensions
sessionToken:sessionToken];
Expand Down
8 changes: 6 additions & 2 deletions Parse/Parse/Internal/CloudCode/PFCloudCodeController.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,14 @@ - (BFTask *)callCloudCodeFunctionAsync:(NSString *)functionName
@weakify(self);
return [[[BFTask taskFromExecutor:[BFExecutor defaultPriorityBackgroundExecutor] withBlock:^id{
@strongify(self);
NSDictionary *encodedParameters = [[PFNoObjectEncoder objectEncoder] encodeObject:parameters];
NSError *error;
NSDictionary *encodedParameters = [[PFNoObjectEncoder objectEncoder] encodeObject:parameters error:&error];
PFPreconditionReturnFailedTask(encodedParameters, error);
PFRESTCloudCommand *command = [PFRESTCloudCommand commandForFunction:functionName
withParameters:encodedParameters
sessionToken:sessionToken];
sessionToken:sessionToken
error:&error];
PFPreconditionReturnFailedTask(command, error);
return [self.dataSource.commandRunner runCommandAsync:command withOptions:PFCommandRunningOptionRetryIfFailed];
}] continueWithSuccessBlock:^id(BFTask *task) {
return ((PFCommandResult *)(task.result)).result[@"result"];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ + (instancetype)constructorWithDataSource:(id<PFInstallationIdentifierStoreProvi
} else {
parameters = command.parameters;
}
requestParameters = [[PFPointerObjectEncoder objectEncoder] encodeObject:parameters];
NSError *error = nil;
requestParameters = [[PFPointerObjectEncoder objectEncoder] encodeObject:parameters error:&error];
PFPreconditionReturnFailedTask(requestParameters, error);
}

return [PFHTTPURLRequestConstructor urlRequestWithURL:url
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ - (void)dealloc {
withOptions:(PFCommandRunningOptions)options
cancellationToken:(BFCancellationToken *)cancellationToken {
return [self _performCommandRunningBlock:^id {
[command resolveLocalIds];
NSError *error;
BOOL success = [command resolveLocalIds:&error];
PFPreconditionReturnFailedTask(success, error);
return [[self.requestConstructor getDataURLRequestAsyncForCommand:command] continueWithSuccessBlock:^id(BFTask <NSURLRequest *>*task) {
return [_session performDataURLRequestAsync:task.result forCommand:command cancellationToken:cancellationToken];
}];
Expand All @@ -168,7 +170,9 @@ - (void)dealloc {
return [self _performCommandRunningBlock:^id {
@strongify(self);

[command resolveLocalIds];
NSError *error;
BOOL success = [command resolveLocalIds:&error];
PFPreconditionReturnFailedTask(success, error);
return [[self.requestConstructor getFileUploadURLRequestAsyncForCommand:command
withContentType:contentType
contentSourceFilePath:sourceFilePath] continueWithSuccessBlock:^id(BFTask<NSURLRequest *> *task) {
Expand Down
5 changes: 3 additions & 2 deletions Parse/Parse/Internal/Commands/PFRESTAnalyticsCommand.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,12 @@ + (instancetype)_trackEventCommandWithEventName:(NSString *)eventName
if (!dictionary[@"at"]) {
dictionary[@"at"] = [NSDate date];
}

// TODO: flovilmart do not swallow error here
return [self commandWithHTTPPath:httpPath
httpMethod:PFHTTPRequestMethodPOST
parameters:dictionary
sessionToken:sessionToken];
sessionToken:sessionToken
error:nil];
}

@end
3 changes: 2 additions & 1 deletion Parse/Parse/Internal/Commands/PFRESTCloudCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ NS_ASSUME_NONNULL_BEGIN

+ (instancetype)commandForFunction:(NSString *)function
withParameters:(nullable NSDictionary *)parameters
sessionToken:(nullable NSString *)sessionToken;
sessionToken:(nullable NSString *)sessionToken
error:(NSError **)error;

@end

Expand Down
6 changes: 4 additions & 2 deletions Parse/Parse/Internal/Commands/PFRESTCloudCommand.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ @implementation PFRESTCloudCommand

+ (instancetype)commandForFunction:(NSString *)function
withParameters:(NSDictionary *)parameters
sessionToken:(NSString *)sessionToken {
sessionToken:(NSString *)sessionToken
error:(NSError **)error {
NSString *path = [NSString stringWithFormat:@"functions/%@", function];
return [self commandWithHTTPPath:path
httpMethod:PFHTTPRequestMethodPOST
parameters:parameters
sessionToken:sessionToken];
sessionToken:sessionToken
error:error];
}

@end
6 changes: 4 additions & 2 deletions Parse/Parse/Internal/Commands/PFRESTCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ NS_ASSUME_NONNULL_BEGIN
+ (instancetype)commandWithHTTPPath:(NSString *)path
httpMethod:(NSString *)httpMethod
parameters:(nullable NSDictionary *)parameters
sessionToken:(nullable NSString *)sessionToken;
sessionToken:(nullable NSString *)sessionToken
error:(NSError **)error;

+ (instancetype)commandWithHTTPPath:(NSString *)path
httpMethod:(NSString *)httpMethod
parameters:(nullable NSDictionary *)parameters
operationSetUUID:(nullable NSString *)operationSetIdentifier
sessionToken:(nullable NSString *)sessionToken;
sessionToken:(nullable NSString *)sessionToken
error:(NSError **)error;

@end

Expand Down
95 changes: 64 additions & 31 deletions Parse/Parse/Internal/Commands/PFRESTCommand.m
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,22 @@ @implementation PFRESTCommand
+ (instancetype)commandWithHTTPPath:(NSString *)path
httpMethod:(NSString *)httpMethod
parameters:(NSDictionary *)parameters
sessionToken:(NSString *)sessionToken {
sessionToken:(NSString *)sessionToken
error:(NSError **) error {
return [self commandWithHTTPPath:path
httpMethod:httpMethod
parameters:parameters
operationSetUUID:nil
sessionToken:sessionToken];
sessionToken:sessionToken
error:error];
}

+ (instancetype)commandWithHTTPPath:(NSString *)path
httpMethod:(NSString *)httpMethod
parameters:(NSDictionary *)parameters
operationSetUUID:(NSString *)operationSetIdentifier
sessionToken:(NSString *)sessionToken {
sessionToken:(NSString *)sessionToken
error:(NSError **)error {
PFRESTCommand *command = [[self alloc] init];
command.httpPath = path;
command.httpMethod = httpMethod;
Expand Down Expand Up @@ -105,12 +108,13 @@ + (instancetype)commandFromDictionaryRepresentation:(NSDictionary *)dictionary {
PFRESTCommand *command = [self commandWithHTTPPath:dictionary[PFRESTCommandHTTPPathEncodingKey]
httpMethod:dictionary[PFRESTCommandHTTPMethodEncodingKey]
parameters:dictionary[PFRESTCommandParametersEncodingKey]
sessionToken:dictionary[PFRESTCommandSessionTokenEncodingKey]];
sessionToken:dictionary[PFRESTCommandSessionTokenEncodingKey]
error:nil];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have to add the error handling here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should be good if I understand the codepaths correctly

command.localId = dictionary[PFRESTCommandLocalIdEncodingKey];
return command;
}

- (NSDictionary *)dictionaryRepresentation {
- (NSDictionary *)dictionaryRepresentation:(NSError **)error {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
if (self.httpPath) {
dictionary[PFRESTCommandHTTPPathEncodingKey] = self.httpPath;
Expand All @@ -119,7 +123,10 @@ - (NSDictionary *)dictionaryRepresentation {
dictionary[PFRESTCommandHTTPMethodEncodingKey] = self.httpMethod;
}
if (self.parameters) {
NSDictionary *parameters = [[PFPointerOrLocalIdObjectEncoder objectEncoder] encodeObject:self.parameters];
NSDictionary *parameters = [[PFPointerOrLocalIdObjectEncoder objectEncoder] encodeObject:self.parameters error:error];
if (!parameters) {
return nil;
}
dictionary[PFRESTCommandParametersEncodingKey] = parameters;
}
if (self.sessionToken) {
Expand All @@ -135,6 +142,7 @@ + (BOOL)isValidDictionaryRepresentation:(NSDictionary *)dictionary {
return dictionary[PFRESTCommandHTTPPathEncodingKey] != nil;
}


#pragma mark Local Identifiers

/**
Expand Down Expand Up @@ -166,66 +174,91 @@ - (void)maybeChangeServerOperation {
}
}

+ (BOOL)forEachLocalIdIn:(id)object doBlock:(BOOL(^)(PFObject *pointer))block {
__block BOOL modified = NO;
+ (BOOL)forEachLocalIdIn:(id)object
doBlock:(BOOL(^)(PFObject *pointer, BOOL *modified, NSError **error))block
modified:(BOOL *)modified error:(NSError **)error {

// If this is a Pointer with a local id, try to resolve it.
if ([object isKindOfClass:[PFObject class]] && !((PFObject *)object).objectId) {
return block(object);
__block BOOL blockModified = NO;
BOOL success = block(object, &blockModified, error);
if (blockModified) {
*modified = YES;
}
return success;
}

if ([object isKindOfClass:[NSDictionary class]]) {
__block NSError *localError;
__block BOOL hasFailed = NO;
[object enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
if ([[self class] forEachLocalIdIn:obj doBlock:block]) {
modified = YES;
if (![[self class] forEachLocalIdIn:obj doBlock:block modified:modified error:&localError]) {
*stop = YES;
hasFailed = YES;
}
}];
if (hasFailed && error) {
*error = localError;
return NO;
}
} else if ([object isKindOfClass:[NSArray class]]) {
for (id value in object) {
if ([[self class] forEachLocalIdIn:value doBlock:block]) {
modified = YES;
if (![[self class] forEachLocalIdIn:value doBlock:block modified:modified error:error]) {
return NO;
}
}
} else if ([object isKindOfClass:[PFAddOperation class]]) {
for (id value in ((PFAddOperation *)object).objects) {
if ([[self class] forEachLocalIdIn:value doBlock:block]) {
modified = YES;
if (![[self class] forEachLocalIdIn:value doBlock:block modified:modified error:error]) {
return NO;
}
}
} else if ([object isKindOfClass:[PFAddUniqueOperation class]]) {
for (id value in ((PFAddUniqueOperation *)object).objects) {
if ([[self class] forEachLocalIdIn:value doBlock:block]) {
modified = YES;
if (![[self class] forEachLocalIdIn:value doBlock:block modified:modified error:error]) {
return NO;
}
}
} else if ([object isKindOfClass:[PFRemoveOperation class]]) {
for (id value in ((PFRemoveOperation *)object).objects) {
if ([[self class] forEachLocalIdIn:value doBlock:block]) {
modified = YES;
if (![[self class] forEachLocalIdIn:value doBlock:block modified:modified error:error]) {
return NO;
}
}
}

return modified;
return YES;
}

- (void)forEachLocalId:(BOOL(^)(PFObject *pointer))block {
- (BOOL)forEachLocalId:(BOOL(^)(PFObject *pointer, BOOL *modified, NSError **error))block error:(NSError **)error {
NSDictionary *data = [[PFDecoder objectDecoder] decodeObject:self.parameters];
if (!data) {
return;
return YES;
}

if ([[self class] forEachLocalIdIn:data doBlock:block]) {
self.parameters = [[PFPointerOrLocalIdObjectEncoder objectEncoder] encodeObject:data];
BOOL modified = NO;
if ([[self class] forEachLocalIdIn:data doBlock:block modified:&modified error:error]) {
self.parameters = [[PFPointerOrLocalIdObjectEncoder objectEncoder] encodeObject:data error:error];
if (self.parameters && !(error && *error)) {
return YES;
}
}
return NO;
}

- (void)resolveLocalIds {
[self forEachLocalId:^(PFObject *pointer) {
[pointer resolveLocalId];
return YES;
}];
- (BOOL)resolveLocalIds:(NSError * __autoreleasing *)error {
BOOL paramEncodingSucceeded = [self forEachLocalId:^(PFObject *pointer, BOOL *modified, NSError **blockError) {
NSError *localError;
BOOL success = [pointer resolveLocalId:&localError];
*modified = YES;
if (!success && localError) {
*blockError = localError;
}
return success;
} error: error];
if (!paramEncodingSucceeded && *error) {
return NO;
}
[self maybeChangeServerOperation];
return YES;
}

@end
6 changes: 4 additions & 2 deletions Parse/Parse/Internal/Commands/PFRESTConfigCommand.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ + (instancetype)configFetchCommandWithSessionToken:(NSString *)sessionToken {
return [self commandWithHTTPPath:@"config"
httpMethod:PFHTTPRequestMethodGET
parameters:nil
sessionToken:sessionToken];
sessionToken:sessionToken
error:nil];
}

+ (instancetype)configUpdateCommandWithConfigParameters:(NSDictionary *)parameters
Expand All @@ -27,7 +28,8 @@ + (instancetype)configUpdateCommandWithConfigParameters:(NSDictionary *)paramete
return [self commandWithHTTPPath:@"config"
httpMethod:PFHTTPRequestMethodPUT
parameters:commandParameters
sessionToken:sessionToken];
sessionToken:sessionToken
error:nil];
}

@end
Loading