Skip to content

Commit

Permalink
TICDS no longer creates sync change objects for changes that occur as…
Browse files Browse the repository at this point in the history
… a result of consuming incoming sync changes. This change should drastically cut down on sync traffic.
  • Loading branch information
Michael Fey committed Apr 19, 2013
1 parent c1891a2 commit 8562e84
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,8 @@ - (void)applyAttributeChangeSyncChange:(TICDSSyncChange *)syncChange
[object willChangeValueForKey:relevantKey];
[object setPrimitiveValue:changedAttributes forKey:relevantKey];
[object didChangeValueForKey:relevantKey];

[TICDSChangeIntegrityStoreManager addChangedAttributeValue:changedAttributes forKey:relevantKey toChangeIntegrityStoreForSyncID:objectSyncID];

TICDSLog(TICDSLogVerbosityManagedObjectOutput, @"Changed attribute on object: %@", object);
}];
Expand Down Expand Up @@ -673,7 +675,9 @@ - (void)applyToOneRelationshipSyncChange:(TICDSSyncChange *)syncChange
[object willChangeValueForKey:relevantKey];
[object setPrimitiveValue:relatedObject forKey:relevantKey];
[object didChangeValueForKey:relevantKey];


[TICDSChangeIntegrityStoreManager addChangedAttributeValue:changedRelationships forKey:relevantKey toChangeIntegrityStoreForSyncID:objectSyncID];

TICDSLog(TICDSLogVerbosityManagedObjectOutput, @"Changed to-one relationship on object: %@", object);
}];
}
Expand Down Expand Up @@ -703,7 +707,7 @@ - (void)applyToManyRelationshipSyncChange:(TICDSSyncChange *)syncChange
return;
}

// capitalize the first char of relationship name to change e.g., someObjects into SomeObjects
// capitalize the first char of relationship name to change e.g., someObject into SomeObject
NSString *relationshipName = [relevantKey substringToIndex:1];
relationshipName = [relationshipName capitalizedString];
relationshipName = [relationshipName stringByAppendingString:[relevantKey substringFromIndex:1]];
Expand All @@ -722,7 +726,7 @@ - (void)applyToManyRelationshipSyncChange:(TICDSSyncChange *)syncChange
[self.synchronizationWarnings addObject:[TICDSUtilities syncWarningOfType:TICDSSyncWarningTypeObjectNotFoundLocallyForRemoteRelationshipSyncChange entityName:relatedObjectEntityName relatedObjectEntityName:nil attributes:changedRelationships]];
return;
}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
if ([object respondsToSelector:NSSelectorFromString(selectorName)]) {
Expand All @@ -732,6 +736,8 @@ - (void)applyToManyRelationshipSyncChange:(TICDSSyncChange *)syncChange
}
#pragma clang diagnostic pop

[TICDSChangeIntegrityStoreManager addChangedAttributeValue:changedRelationships forKey:relevantKey toChangeIntegrityStoreForSyncID:objectSyncID];

TICDSLog(TICDSLogVerbosityManagedObjectOutput, @"%@", objectEntityName);
TICDSLog(TICDSLogVerbosityManagedObjectOutput, @"Changed to-many relationships on object: %@", object);
}];
Expand Down
83 changes: 55 additions & 28 deletions TICoreDataSync/02 Primary Classes/TICDSSynchronizedManagedObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ - (void)createSyncChangesForChangedProperties
{
// separate sync changes are created for each property change, whether it be relationship or attribute
NSDictionary *changedValues = [self changedValues];

NSSet *propertyNamesToBeIgnored = [[self class] keysForWhichSyncChangesWillNotBeCreated];
for( NSString *eachPropertyName in changedValues ) {
if (propertyNamesToBeIgnored != nil && [propertyNamesToBeIgnored containsObject:eachPropertyName]) {
Expand All @@ -97,16 +97,22 @@ - (void)createSyncChangesForChangedProperties

id eachValue = [changedValues valueForKey:eachPropertyName];

NSRelationshipDescription *relationship = [[[self entity] relationshipsByName] valueForKey:eachPropertyName];
if( relationship ) {
[self createSyncChangeIfApplicableForRelationship:relationship];
NSRelationshipDescription *relationshipDescription = [[[self entity] relationshipsByName] valueForKey:eachPropertyName];
if( relationshipDescription ) {
[self createSyncChangeIfApplicableForRelationship:relationshipDescription];
} else {
if ([TICDSChangeIntegrityStoreManager containsChangedAttributeRecordForKey:eachPropertyName withValue:eachValue syncID:self.ticdsSyncID]) {
continue;
}

TICDSSyncChange *syncChange = [self createSyncChangeForChangeType:TICDSSyncChangeTypeAttributeChanged];
TICDSLog(TICDSLogVerbosityManagedObjectOutput, @"[%@] %@", syncChange.objectSyncID, [self class]);
[syncChange setRelevantKey:eachPropertyName];
[syncChange setChangedAttributes:eachValue];
}
}

[TICDSChangeIntegrityStoreManager removeChangedAttributesEntryFromChangeIntegrityStoreForSyncID:self.ticdsSyncID];
}

#pragma mark - Sync Change Helper Methods
Expand All @@ -115,18 +121,17 @@ - (TICDSSyncChange *)createSyncChangeForChangeType:(TICDSSyncChangeType)aType
{
TICDSSyncChange *syncChange = [TICDSSyncChange syncChangeOfType:aType inManagedObjectContext:[self syncChangesMOC]];

TICDSLog(TICDSLogVerbosityManagedObjectOutput, @"[%@] %@", syncChange.objectSyncID, [self class]);

NSString *syncID = self.ticdsSyncID;
if ([syncID length] == 0) {
syncID = [TICDSChangeIntegrityStoreManager ticdsSyncIDForManagedObjectID:self.objectID];
}

[syncChange setObjectSyncID:syncID];
[syncChange setObjectEntityName:[[self entity] name]];
[syncChange setLocalTimeStamp:[NSDate date]];
[syncChange setRelevantManagedObject:self];


TICDSLog(TICDSLogVerbosityManagedObjectOutput, @"[%@] %@", syncChange.objectSyncID, [self class]);
return syncChange;
}

Expand All @@ -146,7 +151,7 @@ - (void)createSyncChangeIfApplicableForRelationship:(NSRelationshipDescription *
// Each check makes sure there _is_ an inverse relationship before checking its type, to allow for relationships with no inverse set

// Check if this is a many-to-one relationship (only sync the -to-one side)
if( ([aRelationship isToMany]) && inverseRelationship && (![inverseRelationship isToMany]) ) {
if( ([aRelationship isToMany]) && inverseRelationship && ([inverseRelationship isToMany] == NO) ) {
return;
}

Expand All @@ -156,7 +161,7 @@ - (void)createSyncChangeIfApplicableForRelationship:(NSRelationshipDescription *
}

// Check if this is a one to one relationship, and only sync the first relationship name alphabetically
if( (![aRelationship isToMany]) && inverseRelationship && (![inverseRelationship isToMany]) && ([[aRelationship name] caseInsensitiveCompare:[inverseRelationship name]] == NSOrderedDescending) ) {
if( ([aRelationship isToMany] == NO) && inverseRelationship && ([inverseRelationship isToMany] == NO) && ([[aRelationship name] caseInsensitiveCompare:[inverseRelationship name]] == NSOrderedDescending) ) {
return;
}

Expand All @@ -169,28 +174,36 @@ - (void)createSyncChangeIfApplicableForRelationship:(NSRelationshipDescription *
// d) edge-case 1: a many-to-many relationship with the same relationship name at both ends (will currently create 2 sync changes)
// e) edge-case 2: a one-to-one relationship with the same relationship name at both ends (will currently create 2 sync changes)

if( ![aRelationship isToMany] ) {
[self createToOneRelationshipSyncChange:aRelationship];
} else {
if ([aRelationship isToMany]) {
[self createToManyRelationshipSyncChanges:aRelationship];
} else {
[self createToOneRelationshipSyncChange:aRelationship];
}
}

- (void)createToOneRelationshipSyncChange:(NSRelationshipDescription *)aRelationship
{
TICDSSyncChange *syncChange = [self createSyncChangeForChangeType:TICDSSyncChangeTypeToOneRelationshipChanged];

TICDSLog(TICDSLogVerbosityManagedObjectOutput, @"[%@] %@", syncChange.objectSyncID, [self class]);
NSString *relevantKey = [aRelationship name];
NSManagedObject *relatedObject = [self valueForKey:relevantKey];

[syncChange setRelatedObjectEntityName:[[aRelationship destinationEntity] name]];
[syncChange setRelevantKey:[aRelationship name]];

NSManagedObject *relatedObject = [self valueForKey:[aRelationship name]];

// Check that the related object should be synchronized
if( [relatedObject isKindOfClass:[TICDSSynchronizedManagedObject class]] ) {
[syncChange setChangedRelationships:[relatedObject valueForKey:TICDSSyncIDAttributeName]];
if ([relatedObject isKindOfClass:[TICDSSynchronizedManagedObject class]] == NO) {
return;
}

NSString *relatedObjectEntityName = [[aRelationship destinationEntity] name];
NSString *relatedObjectSyncID = [relatedObject valueForKey:TICDSSyncIDAttributeName];

if ([TICDSChangeIntegrityStoreManager containsChangedAttributeRecordForKey:relevantKey withValue:relatedObjectSyncID syncID:self.ticdsSyncID]) {
return;
}

TICDSSyncChange *syncChange = [self createSyncChangeForChangeType:TICDSSyncChangeTypeToOneRelationshipChanged];
[syncChange setRelatedObjectEntityName:relatedObjectEntityName];
[syncChange setRelevantKey:relevantKey];
[syncChange setChangedRelationships:relatedObjectSyncID];

TICDSLog(TICDSLogVerbosityManagedObjectOutput, @"[%@] %@", syncChange.objectSyncID, [self class]);
}

- (void)createToManyRelationshipSyncChanges:(NSRelationshipDescription *)aRelationship
Expand All @@ -199,7 +212,7 @@ - (void)createToManyRelationshipSyncChanges:(NSRelationshipDescription *)aRelati
NSDictionary *committedValues = [self committedValuesForKeys:[NSArray arrayWithObject:[aRelationship name]]];

NSSet *previouslyRelatedObjects = [committedValues valueForKey:[aRelationship name]];

NSMutableSet *addedObjects = [NSMutableSet setWithCapacity:5];
for( NSManagedObject *eachObject in relatedObjects ) {
if( ![previouslyRelatedObjects containsObject:eachObject] ) {
Expand All @@ -220,28 +233,42 @@ - (void)createToManyRelationshipSyncChanges:(NSRelationshipDescription *)aRelati
if( ![eachObject isKindOfClass:[TICDSSynchronizedManagedObject class]] ) {
continue;
}

NSString *relevantKey = [aRelationship name];
NSString *relatedObjectSyncID = [eachObject valueForKey:TICDSSyncIDAttributeName];

if ([TICDSChangeIntegrityStoreManager containsChangedAttributeRecordForKey:relevantKey withValue:relatedObjectSyncID syncID:self.ticdsSyncID]) {
continue;
}

eachChange = [self createSyncChangeForChangeType:TICDSSyncChangeTypeToManyRelationshipChangedByAddingObject];

TICDSLog(TICDSLogVerbosityManagedObjectOutput, @"[%@] %@", eachChange.objectSyncID, [self class]);

[eachChange setRelatedObjectEntityName:[[aRelationship destinationEntity] name]];
[eachChange setRelevantKey:[aRelationship name]];
[eachChange setChangedRelationships:[eachObject valueForKey:TICDSSyncIDAttributeName]];
[eachChange setRelevantKey:relevantKey];
[eachChange setChangedRelationships:relatedObjectSyncID];
}

for( NSManagedObject *eachObject in removedObjects ) {
if( ![eachObject isKindOfClass:[TICDSSynchronizedManagedObject class]] ) {
continue;
}

NSString *relevantKey = [aRelationship name];
NSString *relatedObjectSyncID = [eachObject valueForKey:TICDSSyncIDAttributeName];

if ([TICDSChangeIntegrityStoreManager containsChangedAttributeRecordForKey:relevantKey withValue:relatedObjectSyncID syncID:self.ticdsSyncID]) {
continue;
}

eachChange = [self createSyncChangeForChangeType:TICDSSyncChangeTypeToManyRelationshipChangedByRemovingObject];

TICDSLog(TICDSLogVerbosityManagedObjectOutput, @"[%@] %@", eachChange.objectSyncID, [self class]);

[eachChange setRelatedObjectEntityName:[[aRelationship destinationEntity] name]];
[eachChange setRelevantKey:[aRelationship name]];
[eachChange setChangedRelationships:[eachObject valueForKey:TICDSSyncIDAttributeName]];
[eachChange setRelevantKey:relevantKey];
[eachChange setChangedRelationships:relatedObjectSyncID];
}
}

Expand Down
16 changes: 12 additions & 4 deletions TICoreDataSync/04 Utilities/TICDSChangeIntegrityStoreManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,25 @@

+ (TICDSChangeIntegrityStoreManager *)sharedChangeIntegrityStoreManager;

+ (BOOL)containsDeletionRecordForSyncID:(NSString *)ticdsSyncID;
+ (BOOL)containsInsertionRecordForSyncID:(NSString *)ticdsSyncID;
#pragma mark - Deletion Integrity methods

+ (BOOL)containsDeletionRecordForSyncID:(NSString *)ticdsSyncID;
+ (void)addSyncIDToDeletionIntegrityStore:(NSString *)ticdsSyncID;
+ (void)removeSyncIDFromDeletionIntegrityStore:(NSString *)ticdsSyncID;

#pragma mark - Insertion Integrity methods

+ (BOOL)containsInsertionRecordForSyncID:(NSString *)ticdsSyncID;
+ (void)addSyncIDToInsertionIntegrityStore:(NSString *)ticdsSyncID;
+ (void)removeSyncIDFromInsertionIntegrityStore:(NSString *)ticdsSyncID;

+ (void)addChangedProperties:(NSDictionary *)changedProperties toChangeIntegrityStoreForSyncID:(NSString *)ticdsSyncID;
+ (void)removeChangedProperties:(NSDictionary *)changedProperties fromChangeIntegrityStoreForSyncID:(NSString *)ticdsSyncID;
#pragma mark - Change Integrity methods

+ (BOOL)containsChangedAttributeRecordForKey:(id)key withValue:(id)value syncID:(NSString *)ticdsSyncID;
+ (void)addChangedAttributeValue:(id)value forKey:(id)key toChangeIntegrityStoreForSyncID:(NSString *)ticdsSyncID;
+ (void)removeChangedAttributesEntryFromChangeIntegrityStoreForSyncID:(NSString *)ticdsSyncID;

#pragma mark - Undo Integrity methods

+ (void)storeTICDSSyncID:(NSString *)ticdsSyncID forManagedObjectID:(NSManagedObjectID *)managedObjectID;
+ (NSString *)ticdsSyncIDForManagedObjectID:(NSManagedObjectID *)managedObjectID;
Expand Down
87 changes: 58 additions & 29 deletions TICoreDataSync/04 Utilities/TICDSChangeIntegrityStoreManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,16 @@ @implementation TICDSChangeIntegrityStoreManager
@synthesize deletionSet = _deletionSet;
@synthesize changeDictionary = _changeDictionary;

#pragma mark - Public methods
#pragma mark - Deletion Integrity methods

+ (BOOL)containsDeletionRecordForSyncID:(NSString *)ticdsSyncID
{
BOOL containsDeletionRecord = NO;
@synchronized(deletionStoreLock) {
containsDeletionRecord = [[[self sharedChangeIntegrityStoreManager] deletionSet] containsObject:ticdsSyncID];
}

return containsDeletionRecord;
}

+ (BOOL)containsInsertionRecordForSyncID:(NSString *)ticdsSyncID;
{
BOOL containsInsertionRecord = NO;
@synchronized(insertionStoreLock) {
containsInsertionRecord = [[[self sharedChangeIntegrityStoreManager] insertionSet] containsObject:ticdsSyncID];
}

return containsInsertionRecord;
return containsDeletionRecord;
}

+ (void)addSyncIDToDeletionIntegrityStore:(NSString *)ticdsSyncID
Expand All @@ -62,6 +52,18 @@ + (void)removeSyncIDFromDeletionIntegrityStore:(NSString *)ticdsSyncID
}
}

#pragma mark - Insertion Integrity methods

+ (BOOL)containsInsertionRecordForSyncID:(NSString *)ticdsSyncID;
{
BOOL containsInsertionRecord = NO;
@synchronized(insertionStoreLock) {
containsInsertionRecord = [[[self sharedChangeIntegrityStoreManager] insertionSet] containsObject:ticdsSyncID];
}

return containsInsertionRecord;
}

+ (void)addSyncIDToInsertionIntegrityStore:(NSString *)ticdsSyncID
{
@synchronized(insertionStoreLock) {
Expand All @@ -76,28 +78,56 @@ + (void)removeSyncIDFromInsertionIntegrityStore:(NSString *)ticdsSyncID
}
}

+ (void)addChangedProperties:(NSDictionary *)changedProperties toChangeIntegrityStoreForSyncID:(NSString *)ticdsSyncID
#pragma mark - Change Integrity methods

+ (BOOL)containsChangedAttributeRecordForKey:(id)key withValue:(id)value syncID:(NSString *)ticdsSyncID
{
@synchronized(changeStoreLock) {
NSDictionary *storedAttributes = [[[self sharedChangeIntegrityStoreManager] changeDictionary] objectForKey:ticdsSyncID];
if (storedAttributes == nil) {
return NO;
}

id storedValue = [storedAttributes objectForKey:key];
if (storedValue == nil) {
return NO;
}

return [storedValue isEqualTo:value];
}
}

+ (void)addChangedAttributeValue:(id)value forKey:(id)key toChangeIntegrityStoreForSyncID:(NSString *)ticdsSyncID
{
// @synchronized(changeStoreLock) {
// NSMutableDictionary *previouslyChangedProperties = [[[self sharedChangeIntegrityStoreManager] changeDictionary] objectForKey:ticdsSyncID];
// if (previouslyChangedProperties == nil) {
// previouslyChangedProperties = [NSMutableDictionary dictionaryWithDictionary:changedProperties];
// } else {
// NSArray *keys = [previouslyChangedProperties allKeys];
//
// }
//
// [[[self sharedChangeIntegrityStoreManager] changeDictionary] setObject:previouslyChangedProperties forKey:ticdsSyncID];
// }
if (key == nil) {
return;
}

@synchronized(changeStoreLock) {
NSMutableDictionary *storedAttributes = [[[self sharedChangeIntegrityStoreManager] changeDictionary] objectForKey:ticdsSyncID];
if (storedAttributes == nil) {
storedAttributes = [NSMutableDictionary dictionary];
}

if (value == nil) {
[storedAttributes removeObjectForKey:key];
} else {
[storedAttributes setObject:value forKey:key];
}

[[[self sharedChangeIntegrityStoreManager] changeDictionary] setObject:storedAttributes forKey:ticdsSyncID];
}
}

+ (void)removeChangedProperties:(NSDictionary *)changedProperties fromChangeIntegrityStoreForSyncID:(NSString *)ticdsSyncID
+ (void)removeChangedAttributesEntryFromChangeIntegrityStoreForSyncID:(NSString *)ticdsSyncID
{
// @synchronized(changeStoreLock) {
//
// }
@synchronized(changeStoreLock) {
[[[self sharedChangeIntegrityStoreManager] changeDictionary] removeObjectForKey:ticdsSyncID];
}
}

#pragma mark - Undo Integrity methods

+ (void)storeTICDSSyncID:(NSString *)ticdsSyncID forManagedObjectID:(NSManagedObjectID *)managedObjectID
{
if ([ticdsSyncID length] == 0) {
Expand All @@ -118,7 +148,6 @@ + (NSString *)ticdsSyncIDForManagedObjectID:(NSManagedObjectID *)managedObjectID
return syncID;
}


#pragma mark - Overridden getters/setters

- (NSMutableSet *)deletionSet
Expand Down

0 comments on commit 8562e84

Please sign in to comment.