Skip to content
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

Enabling JSONStorage Support #606

Merged
merged 20 commits into from
Jan 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions Simperium.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
B57421D52510FA67006F2A71 /* NSURLRequest+Simperium.h in Headers */ = {isa = PBXBuildFile; fileRef = B57421D22510FA67006F2A71 /* NSURLRequest+Simperium.h */; };
B57421D62510FA67006F2A71 /* NSURLRequest+Simperium.m in Sources */ = {isa = PBXBuildFile; fileRef = B57421D32510FA67006F2A71 /* NSURLRequest+Simperium.m */; };
B57421D72510FA67006F2A71 /* NSURLRequest+Simperium.m in Sources */ = {isa = PBXBuildFile; fileRef = B57421D32510FA67006F2A71 /* NSURLRequest+Simperium.m */; };
B57CFA1C25B10B7100ABA284 /* SPThreadsafeMutableDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = B57CFA1A25B10B7100ABA284 /* SPThreadsafeMutableDictionary.h */; };
B57CFA1D25B10B7100ABA284 /* SPThreadsafeMutableDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = B57CFA1A25B10B7100ABA284 /* SPThreadsafeMutableDictionary.h */; };
B57CFA1E25B10B7100ABA284 /* SPThreadsafeMutableDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = B57CFA1B25B10B7100ABA284 /* SPThreadsafeMutableDictionary.m */; };
B57CFA1F25B10B7100ABA284 /* SPThreadsafeMutableDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = B57CFA1B25B10B7100ABA284 /* SPThreadsafeMutableDictionary.m */; };
B57CFA2925B1100600ABA284 /* SPThreadsafeMutableDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B57CFA2825B1100600ABA284 /* SPThreadsafeMutableDictionaryTests.m */; };
B57FA3AE190052C800957205 /* MockStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = B57FA3AD190052C800957205 /* MockStorage.m */; };
B57FA3B21900568A00957205 /* SPRelationshipResolverTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B57FA3B11900568A00957205 /* SPRelationshipResolverTests.m */; };
B585125A2485FE32002BD70C /* SPAuthenticationValidatorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B58512592485FE32002BD70C /* SPAuthenticationValidatorTests.m */; };
Expand Down Expand Up @@ -603,6 +608,9 @@
B5728F9B250FD4A700D1DA07 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk/System/Library/Frameworks/CoreServices.framework; sourceTree = DEVELOPER_DIR; };
B57421D22510FA67006F2A71 /* NSURLRequest+Simperium.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSURLRequest+Simperium.h"; sourceTree = "<group>"; };
B57421D32510FA67006F2A71 /* NSURLRequest+Simperium.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSURLRequest+Simperium.m"; sourceTree = "<group>"; };
B57CFA1A25B10B7100ABA284 /* SPThreadsafeMutableDictionary.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SPThreadsafeMutableDictionary.h; sourceTree = "<group>"; };
B57CFA1B25B10B7100ABA284 /* SPThreadsafeMutableDictionary.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SPThreadsafeMutableDictionary.m; sourceTree = "<group>"; };
B57CFA2825B1100600ABA284 /* SPThreadsafeMutableDictionaryTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SPThreadsafeMutableDictionaryTests.m; sourceTree = "<group>"; };
B57FA3AC190052C800957205 /* MockStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockStorage.h; sourceTree = "<group>"; };
B57FA3AD190052C800957205 /* MockStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MockStorage.m; sourceTree = "<group>"; };
B57FA3B11900568A00957205 /* SPRelationshipResolverTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPRelationshipResolverTests.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -900,6 +908,8 @@
24A73F5517E250E0000CA275 /* SPPersistentMutableDictionary.m */,
B5EC2C2318858E3E0067E3B8 /* SPPersistentMutableSet.h */,
B5EC2C2418858E3E0067E3B8 /* SPPersistentMutableSet.m */,
B57CFA1A25B10B7100ABA284 /* SPThreadsafeMutableDictionary.h */,
B57CFA1B25B10B7100ABA284 /* SPThreadsafeMutableDictionary.m */,
B5549FE118457F72007EA226 /* SPThreadsafeMutableSet.h */,
B5549FE218457F72007EA226 /* SPThreadsafeMutableSet.m */,
B5EB86981822E34F007450FF /* SPLogger.h */,
Expand Down Expand Up @@ -1232,6 +1242,7 @@
B5C7D7F8183411B900E9109C /* SPPersistentMutableDictionaryTests.m */,
B5EC2C27188595420067E3B8 /* SPPersistentMutableSetTests.m */,
B5549FE5184581BF007EA226 /* SPThreadsafeMutableSetTests.m */,
B57CFA2825B1100600ABA284 /* SPThreadsafeMutableDictionaryTests.m */,
B597DD58183128FE005E95D7 /* SPWebSocketInterfaceTests.m */,
B5DE0E0E1850D0200080C44D /* SPCoreDataStorageTests.m */,
B5DF229418B41FB700874C75 /* SPMemberJSONTests.m */,
Expand Down Expand Up @@ -1359,6 +1370,7 @@
B5FC08BA1D662D5300045DB9 /* TrustKit+Private.h in Headers */,
B5CAA4C11CAAB40F006FE048 /* SPNetworkInterface.h in Headers */,
B5CAA4C61CAAB44E006FE048 /* SPStorageProvider.h in Headers */,
B57CFA1C25B10B7100ABA284 /* SPThreadsafeMutableDictionary.h in Headers */,
B5CAA4C01CAAB405006FE048 /* SPUser.h in Headers */,
B5CAA4C81CAAB50E006FE048 /* SPSwizzle.h in Headers */,
B5FC08A21D662D5300045DB9 /* parse_configuration.h in Headers */,
Expand Down Expand Up @@ -1441,6 +1453,7 @@
B5F6A4C3251024380001D7E3 /* NSURLSession+Simperium.h in Headers */,
B5CAA5BA1CAAED3D006FE048 /* Simperium.h in Headers */,
B5A8773522DCD37F00FC22C7 /* SPAuthenticationInterface.h in Headers */,
B57CFA1D25B10B7100ABA284 /* SPThreadsafeMutableDictionary.h in Headers */,
B5CAA5BC1CAAED3D006FE048 /* SPAuthenticationConfiguration.h in Headers */,
B5CAA5BD1CAAED3D006FE048 /* SPAuthenticator.h in Headers */,
B5CAA5BE1CAAED3D006FE048 /* SPBucket.h in Headers */,
Expand Down Expand Up @@ -1776,6 +1789,7 @@
B5CAA5491CAABC16006FE048 /* SPNetworkInterface.m in Sources */,
B5CAA54A1CAABC1D006FE048 /* SPProcessorConstants.m in Sources */,
B5CAA6511CAAF2F8006FE048 /* SPAuthenticationViewController.m in Sources */,
B57CFA1E25B10B7100ABA284 /* SPThreadsafeMutableDictionary.m in Sources */,
B5CAA54B1CAABC23006FE048 /* NSError+Simperium.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -1860,6 +1874,7 @@
B5CAA5AD1CAAED3D006FE048 /* SPNetworkInterface.m in Sources */,
B5CAA5AE1CAAED3D006FE048 /* SPProcessorConstants.m in Sources */,
B5CAA5AF1CAAED3D006FE048 /* NSError+Simperium.m in Sources */,
B57CFA1F25B10B7100ABA284 /* SPThreadsafeMutableDictionary.m in Sources */,
B5CAA63E1CAAF1D9006FE048 /* SPAuthenticationButtonCell.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -1868,6 +1883,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B57CFA2925B1100600ABA284 /* SPThreadsafeMutableDictionaryTests.m in Sources */,
B53F75A91A1BAB4600C0DDFB /* SPStorageObserverAdapter.m in Sources */,
B565ECA31832643000D162FF /* TestObject.m in Sources */,
B57FA3AE190052C800957205 /* MockStorage.m in Sources */,
Expand Down
12 changes: 9 additions & 3 deletions Simperium/SPBucket.m
Original file line number Diff line number Diff line change
Expand Up @@ -158,19 +158,25 @@ - (void)statsWithCallback:(SPBucketStatsCallback)callback {
}

- (NSString *)lastChangeSignature {
if (!_lastChangeSignature) {
// Load it
// Load it: Skip for Ephemeral Storage
if (!_lastChangeSignature && !_storage.isEphemeral) {
NSString *sigKey = [NSString stringWithFormat:@"lastChangeSignature-%@", self.instanceLabel];
NSString *signature = [[NSUserDefaults standardUserDefaults] objectForKey:sigKey];
_lastChangeSignature = [signature copy];
}

return _lastChangeSignature;
}

- (void)setLastChangeSignature:(NSString *)signature {

_lastChangeSignature = [signature copy];

// Persist it
// Persist it: Skip for Ephemeral Storage
if (self.storage.isEphemeral) {
return;
}

NSString *sigKey = [NSString stringWithFormat:@"lastChangeSignature-%@", self.instanceLabel];
[[NSUserDefaults standardUserDefaults] setObject:_lastChangeSignature forKey: sigKey];
[[NSUserDefaults standardUserDefaults] synchronize];
Expand Down
4 changes: 4 additions & 0 deletions Simperium/SPCoreDataStorage.m
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,10 @@ - (NSSet *)stashedObjects {
return [self.privateStashedObjects copy];
}

- (BOOL)isEphemeral {
return NO;
}


#pragma mark - Stashing and unstashing entities

Expand Down
4 changes: 2 additions & 2 deletions Simperium/SPDiffable.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
@property (nonatomic, copy) NSString *ghostData;
@property (nonatomic, copy) NSString *simperiumKey;
@property (nonatomic, weak) SPBucket *bucket;
@property (nonatomic, copy, readonly) NSDictionary *dictionary;
@property (nonatomic, copy, readonly) NSString *version;

- (void)simperiumSetValue:(id)value forKey:(NSString *)key;
- (id)simperiumValueForKey:(NSString *)key;
- (void)loadMemberData:(NSDictionary *)data;
- (void)willBeRead;
- (NSDictionary *)dictionary;
- (NSString *)version;
- (id)object;

@optional
Expand Down
9 changes: 8 additions & 1 deletion Simperium/SPDiffer.m
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,11 @@ - (BOOL)applyDiffFromDictionary:(NSDictionary *)diff toObject:(id<SPDiffable>)ob
if (change == nil) {
continue;
}


// Dynamic Schema: Ensure the Member is available
// TODO: Implement Support for Dynamic Members with different encoding
[self.schema ensureDynamicMemberExistsForObject:key key:change[OP_VALUE]];

// Make sure the member exists and is tracked by Simperium
SPMember *member = [self.schema memberForKey:key];
if (!member) {
Expand Down Expand Up @@ -181,6 +185,9 @@ - (BOOL)applyGhostDiffFromDictionary:(NSDictionary *)diff toObject:(id<SPDiffabl
if (change == nil) {
continue;
}

// Dynamic Schema: Ensure the Member is available
[self.schema ensureDynamicMemberExistsForObject:change[OP_VALUE] key:key];

// Make sure the member exists and is tracked by Simperium
SPMember *member = [self.schema memberForKey:key];
Expand Down
43 changes: 20 additions & 23 deletions Simperium/SPJSONStorage.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@
#import "SPObject.h"
#import "SPGhost.h"
#import "NSString+Simperium.h"
#import "NSMutableDictionary+Simperium.h"
#import "SPBucket+Internals.h"
#import "SPSchema.h"
#import "SPDiffer.h"
#import "SPswizzle.h"


@interface NSMutableDictionary ()
Expand Down Expand Up @@ -44,10 +42,6 @@ - (instancetype)initWithDelegate:(id<SPStorageObserver>)aDelegate

NSString *queueLabel = @"com.simperium.JSONstorage";
_storageQueue = dispatch_queue_create([queueLabel cStringUsingEncoding:NSUTF8StringEncoding], NULL);

NSError *error = nil;
[NSMutableDictionary sp_swizzleMethod:@selector(setObject:forKey:) withMethod:@selector(simperiumSetObject:forKey:) error:&error];
[NSMutableDictionary sp_swizzleMethod:@selector(setValue:forKey:) withMethod:@selector(simperiumSetValue:forKey:) error:&error];
}
Comment on lines -49 to 45

Choose a reason for hiding this comment

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

🔥


return self;
Expand All @@ -57,9 +51,7 @@ - (instancetype)initWithDelegate:(id<SPStorageObserver>)aDelegate
- (void)object:(id)object forKey:(NSString *)simperiumKey didChangeValue:(id)value forKey:(NSString *)key {
// Update the schema if applicable
SPObject *spObject = [_allObjects objectForKey:simperiumKey];
[spObject.bucket.differ.schema addMemberForObject:value key:key];

// TODO: track the change here so saving can be smart
[spObject.bucket.differ.schema ensureDynamicMemberExistsForObject:value key:key];
}

- (SPStorage *)threadSafeStorage {
Expand Down Expand Up @@ -94,11 +86,7 @@ - (NSArray *)objectsForKeys:(NSSet *)keys bucketName:(NSString *)bucketName
}
});

if (!someObjects) {
someObjects = @[];
}

return someObjects;
return someObjects ?: @[];
}

- (id)objectAtIndex:(NSUInteger)index bucketName:(NSString *)bucketName {
Expand All @@ -111,25 +99,25 @@ - (NSArray *)objectsForBucketName:(NSString *)bucketName predicate:(NSPredicate
dispatch_sync(_storageQueue, ^{
NSDictionary *objectDict = [_objects objectForKey:bucketName];
if (objectDict) {
bucketObjects = [_objects allValues];
bucketObjects = [objectDict allValues];

if (predicate)
if (predicate) {
bucketObjects = [bucketObjects filteredArrayUsingPredicate:predicate];
}
}
});

if (!bucketObjects) {
bucketObjects = @[];
}
return bucketObjects;

return bucketObjects ?: @[];
}

- (NSArray *)objectKeysForBucketName:(NSString *)bucketName {
__block NSArray *bucketObjects = [self objectsForBucketName:bucketName predicate:nil];

NSMutableArray *keys = [NSMutableArray arrayWithCapacity:[bucketObjects count]];
for (id<SPDiffable>object in bucketObjects) {
[keys addObject:[object simperiumKey]];
if (object.simperiumKey) {
[keys addObject:object.simperiumKey];
}
}

return keys;
Expand Down Expand Up @@ -303,15 +291,20 @@ - (BOOL)save {
// triggered from the main thread and could take awhile

// Sync all changes: Fake it for now by trying to send all objects

// TODO: JSONStorage is readonly at this stage.
// Local changes should be captured via `didChangeValue:forKey:`
/*
NSMutableSet *updatedObjects = [NSMutableSet set];

for (NSDictionary *objectDict in _objects.allValues) {
NSArray *objectsAsList = [objectDict allValues];
[updatedObjects addObjectsFromArray:objectsAsList];
}
*/

[_delegate storageWillSave:self deletedObjects:nil];
[_delegate storageDidSave:self insertedObjects:nil updatedObjects:updatedObjects];
[_delegate storageDidSave:self insertedObjects:nil updatedObjects:nil];

return NO;
}
Expand All @@ -337,6 +330,10 @@ - (NSSet *)stashedObjects {
return nil;
}

- (BOOL)isEphemeral {
return YES;
}

- (void)stashUnsavedObjects {
// NO-OP
}
Expand Down
9 changes: 3 additions & 6 deletions Simperium/SPObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@
#import <Foundation/Foundation.h>
#import "SPDiffable.h"

@interface SPObject : NSObject<SPDiffable> {
NSMutableDictionary *dict;
NSString *simperiumKey;
}
@interface SPObject : NSObject<SPDiffable>

@property (nonatomic, strong) NSMutableDictionary *dict;
@property (nonatomic, strong) SPGhost *ghost;
@property (nonatomic, copy) NSString *ghostData;
@property (nonatomic, copy) NSString *simperiumKey;
@property (nonatomic, copy) NSString *version;
@property (nonatomic, copy, readonly) NSString *version;
@property (nonatomic, copy, readonly) NSDictionary *dictionary;

- (instancetype)initWithDictionary:(NSMutableDictionary *)dictionary;

Expand Down