Skip to content

Commit

Permalink
Rework sync config initialization
Browse files Browse the repository at this point in the history
Calculate the path from the partition value when a RLMSyncConfiguration is
constructed rather than when it's set on a RLMRealmConfiguration, and change
RealmSwift.SyncConfiguration to wrap a RLMSyncConfiguration rather than copying
the values out. In combination, these changes make it so that we only calculate
the path when the configuration is constructed, rather than every time a Realm
instance is obtained.
  • Loading branch information
tgoyne committed Jun 30, 2022
1 parent 1f56b9b commit e0d0398
Show file tree
Hide file tree
Showing 16 changed files with 237 additions and 266 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
x.y.z Release notes (yyyy-MM-dd)
=============================================================
### Enhancements
* None.
* Greatly improve the performance of obtaining cached Realm instances in Swift
when using a sync configuration.

### Fixed
* <How to hit and notice issue? what was the impact?> ([#????](https://github.com/realm/realm-swift/issues/????), since v?.?.?)
Expand Down
22 changes: 11 additions & 11 deletions Realm/ObjectServerTests/SwiftObjectServerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ class SwiftObjectServerTests: SwiftSyncTestCase {

waitForSyncDisabled(appServerId: appServerId, syncServiceId: syncServiceId)

try block()
try autoreleasepool(invoking: block)

waitForSyncEnabled(appServerId: appServerId, syncServiceId: syncServiceId, syncServiceConfig: syncServiceConfig)
try waitForDevModeEnabled(appServerId: appServerId, syncServiceId: syncServiceId, syncServiceConfig: syncServiceConfig)
Expand Down Expand Up @@ -436,16 +436,15 @@ class SwiftObjectServerTests: SwiftSyncTestCase {

// Sync is disabled, block executed, sync re-enabled
try executeBlockOffline {
try autoreleasepool {
var configuration = user.configuration(partitionValue: partition)
configuration.objectTypes = [SwiftPerson.self]
let realm = try Realm(configuration: configuration)
// Add an object to the local realm that will not be in the server realm (because sync is disabled).
try realm.write {
realm.add(SwiftPerson(firstName: "John", lastName: "L"))
}
XCTAssertEqual(realm.objects(SwiftPerson.self).count, 1)
var configuration = user.configuration(partitionValue: partition)
configuration.objectTypes = [SwiftPerson.self]
let realm = try Realm(configuration: configuration)
realm.syncSession!.suspend()
// Add an object to the local realm that will not be in the server realm (because sync is disabled).
try realm.write {
realm.add(SwiftPerson(firstName: "John", lastName: "L"))
}
XCTAssertEqual(realm.objects(SwiftPerson.self).count, 1)
}

// After restarting sync, the sync history translator service needs time
Expand Down Expand Up @@ -498,7 +497,8 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
afterCallbackEx.fulfill()
}

var configuration = user.configuration(partitionValue: #function, clientResetMode: .discardLocal(beforeClientResetBlock, afterClientResetBlock))
var configuration = user.configuration(partitionValue: #function,
clientResetMode: .discardLocal(beforeClientResetBlock, afterClientResetBlock))
configuration.objectTypes = [SwiftPerson.self]

guard let syncConfig = configuration.syncConfiguration else { fatalError("Test condition failure. SyncConfiguration not set.") }
Expand Down
2 changes: 1 addition & 1 deletion Realm/RLMApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Create a new Realm App configuration.
*/
- (instancetype)initWithBaseURL:(nullable NSString *) baseURL
transport:(nullable id<RLMNetworkTransport>)transport
localAppName:(nullable NSString *) localAppName
localAppName:(nullable NSString *)localAppName
localAppVersion:(nullable NSString *)localAppVersion
defaultRequestTimeoutMS:(NSUInteger)defaultRequestTimeoutMS;

Expand Down
9 changes: 8 additions & 1 deletion Realm/RLMApp.mm
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ - (instancetype)initWithConfig:(const realm::app::App::Config &)config {
return nil;
}

- (instancetype)init {
return [self initWithBaseURL:nil
transport:nil
localAppName:nil
localAppVersion:nil];
}

- (instancetype)initWithBaseURL:(nullable NSString *)baseURL
transport:(nullable id<RLMNetworkTransport>)transport
localAppName:(nullable NSString *)localAppName
Expand All @@ -111,7 +118,7 @@ - (instancetype)initWithBaseURL:(nullable NSString *)baseURL

- (instancetype)initWithBaseURL:(nullable NSString *)baseURL
transport:(nullable id<RLMNetworkTransport>)transport
localAppName:(NSString *)localAppName
localAppName:(nullable NSString *)localAppName
localAppVersion:(nullable NSString *)localAppVersion
defaultRequestTimeoutMS:(NSUInteger)defaultRequestTimeoutMS {
if (self = [super init]) {
Expand Down
17 changes: 6 additions & 11 deletions Realm/RLMRealmConfiguration.mm
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,9 @@ - (void)setInMemoryIdentifier:(NSString *)inMemoryIdentifier {

- (void)setSeedFilePath:(NSURL *)seedFilePath {
_seedFilePath = seedFilePath;
_config.in_memory = false;
if (_seedFilePath) {
_config.in_memory = false;
}
}

- (NSData *)encryptionKey {
Expand Down Expand Up @@ -354,15 +356,8 @@ - (void)setSyncConfiguration:(RLMSyncConfiguration *)syncConfiguration {

NSAssert(user.identifier, @"Cannot call this method on a user that doesn't have an identifier.");
_config.in_memory = false;
_config.sync_config = std::make_shared<realm::SyncConfig>([syncConfiguration rawConfiguration]);

if (syncConfiguration.customFileURL) {
_config.path = syncConfiguration.customFileURL.path.UTF8String;
} else if (_config.sync_config->flx_sync_requested) {
_config.path = [user pathForFlexibleSync];
} else {
_config.path = [user pathForPartitionValue:_config.sync_config->partition_value];
}
_config.sync_config = std::make_shared<realm::SyncConfig>(syncConfiguration.rawConfiguration);
_config.path = syncConfiguration.path;

[self updateSchemaMode];
}
Expand All @@ -371,7 +366,7 @@ - (RLMSyncConfiguration *)syncConfiguration {
if (!_config.sync_config) {
return nil;
}
return [[RLMSyncConfiguration alloc] initWithRawConfig:*_config.sync_config];
return [[RLMSyncConfiguration alloc] initWithRawConfig:*_config.sync_config path:_config.path];
}

#else // REALM_ENABLE_SYNC
Expand Down
10 changes: 0 additions & 10 deletions Realm/RLMSyncConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,6 @@ typedef void(^RLMClientResetAfterBlock)(RLMRealm * _Nonnull beforeFrozen, RLMRea
*/
@property (nonatomic) bool cancelAsyncOpenOnNonFatalErrors;

/// :nodoc:
- (instancetype)initWithUser:(RLMUser *)user
partitionValue:(nullable id<RLMBSON>)partitionValue __attribute__((unavailable("Use [RLMUser configurationWithPartitionValue:] instead")));

/// :nodoc:
+ (RLMRealmConfiguration *)automaticConfiguration __attribute__((unavailable("Use [RLMUser configuration] instead")));

/// :nodoc:
+ (RLMRealmConfiguration *)automaticConfigurationForUser:(RLMUser *)user __attribute__((unavailable("Use [RLMUser configuration] instead")));

/// :nodoc:
- (instancetype)init __attribute__((unavailable("This type cannot be created directly")));

Expand Down
182 changes: 56 additions & 126 deletions Realm/RLMSyncConfiguration.mm
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,10 @@ @implementation RLMSyncConfiguration

@dynamic stopPolicy;

- (instancetype)initWithRawConfig:(realm::SyncConfig)config {
- (instancetype)initWithRawConfig:(realm::SyncConfig)config path:(std::string const&)path {
if (self = [super init]) {
_config = std::make_unique<realm::SyncConfig>(std::move(config));
_path = path;
}
return self;
}
Expand All @@ -126,8 +127,8 @@ - (BOOL)isEqual:(id)object {
}
RLMSyncConfiguration *that = (RLMSyncConfiguration *)object;
return [self.partitionValue isEqual:that.partitionValue]
&& [self.user isEqual:that.user]
&& self.stopPolicy == that.stopPolicy;
&& [self.user isEqual:that.user]
&& self.stopPolicy == that.stopPolicy;
}

- (realm::SyncConfig&)rawConfiguration {
Expand All @@ -151,6 +152,10 @@ - (RLMClientResetMode)clientResetMode {
return RLMClientResetMode(_config->client_resync_mode);
}

- (void)setClientResetMode:(RLMClientResetMode)clientResetMode {
_config->client_resync_mode = realm::ClientResyncMode(clientResetMode);
}

- (RLMClientResetBeforeBlock)beforeClientReset {
if (_config->notify_before_client_reset) {
auto wrapper = _config->notify_before_client_reset.target<BeforeClientResetWrapper>();
Expand Down Expand Up @@ -223,79 +228,6 @@ - (BOOL)enableFlexibleSync {
return _config->flx_sync_requested;
}

- (instancetype)initWithUser:(RLMUser *)user
partitionValue:(nullable id<RLMBSON>)partitionValue {
return [self initWithUser:user
partitionValue:partitionValue
customFileURL:nil
stopPolicy:RLMSyncStopPolicyAfterChangesUploaded
enableFlexibleSync:false
clientResetMode:RLMClientResetModeManual
notifyBeforeReset:nil
notifyAfterReset:nil];
}

- (instancetype)initWithUser:(RLMUser *)user
partitionValue:(nullable id<RLMBSON>)partitionValue
stopPolicy:(RLMSyncStopPolicy)stopPolicy
clientResetMode:(RLMClientResetMode)clientResetMode
notifyBeforeReset:(nullable RLMClientResetBeforeBlock)beforeResetBlock
notifyAfterReset:(nullable RLMClientResetAfterBlock)afterResetBlock {
auto config = [self initWithUser:user
partitionValue:partitionValue
customFileURL:nil
stopPolicy:stopPolicy
enableFlexibleSync:false
clientResetMode:clientResetMode
notifyBeforeReset:beforeResetBlock
notifyAfterReset:afterResetBlock];
return config;
}

- (instancetype)initWithUser:(RLMUser *)user
stopPolicy:(RLMSyncStopPolicy)stopPolicy
enableFlexibleSync:(BOOL)enableFlexibleSync {
auto config = [self initWithUser:user
partitionValue:nil
customFileURL:nil
stopPolicy:stopPolicy
enableFlexibleSync:enableFlexibleSync
clientResetMode:RLMClientResetModeManual
notifyBeforeReset:nil
notifyAfterReset:nil];
return config;
}



- (instancetype)initWithUser:(RLMUser *)user
partitionValue:(nullable id<RLMBSON>)partitionValue
clientResetMode:(RLMClientResetMode)clientResetMode {
auto config = [self initWithUser:user
partitionValue:partitionValue
customFileURL:nil
stopPolicy:RLMSyncStopPolicyAfterChangesUploaded
enableFlexibleSync:false
clientResetMode:clientResetMode
notifyBeforeReset:nil
notifyAfterReset:nil];
return config;
}

- (instancetype)initWithUser:(RLMUser *)user
enableFlexibleSync:(BOOL)enableFlexibleSync
clientResetMode:(RLMClientResetMode)clientResetMode {
auto config = [self initWithUser:user
partitionValue:nil
customFileURL:nil
stopPolicy:RLMSyncStopPolicyAfterChangesUploaded
enableFlexibleSync:enableFlexibleSync
clientResetMode:clientResetMode
notifyBeforeReset:nil
notifyAfterReset:nil];
return config;
}

NSError *RLMTranslateSyncError(SyncError error) {
NSString *recoveryPath;
RLMSyncErrorActionToken *token;
Expand Down Expand Up @@ -338,61 +270,59 @@ - (instancetype)initWithUser:(RLMUser *)user
return make_sync_error(errorClass, @(error.message.c_str()), error.error_code.value(), custom);
}

- (instancetype)initWithUser:(RLMUser *)user
partitionValue:(nullable id<RLMBSON>)partitionValue
customFileURL:(nullable NSURL *)customFileURL
stopPolicy:(RLMSyncStopPolicy)stopPolicy
enableFlexibleSync:(BOOL)enableFlexibleSync
clientResetMode:(RLMClientResetMode)clientResetMode
notifyBeforeReset:(RLMClientResetBeforeBlock)beforeResetBlock
notifyAfterReset:(RLMClientResetAfterBlock)afterResetBlock {
if (self = [super init]) {
if (enableFlexibleSync) {
_config = std::make_unique<SyncConfig>([user _syncUser], SyncConfig::FLXSyncEnabled{});
} else {
std::stringstream s;
s << RLMConvertRLMBSONToBson(partitionValue);
_config = std::make_unique<SyncConfig>([user _syncUser],
s.str());
static void setDefaults(SyncConfig& config, RLMUser *user) {
config.client_resync_mode = ClientResyncMode::Manual;
config.stop_policy = SyncSessionStopPolicy::AfterChangesUploaded;

RLMSyncManager *manager = [user.app syncManager];
__weak RLMSyncManager *weakManager = manager;
config.error_handler = [weakManager](std::shared_ptr<SyncSession> errored_session, SyncError error) {
RLMSyncErrorReportingBlock errorHandler;
@autoreleasepool {
errorHandler = weakManager.errorHandler;
}
_config->stop_policy = translateStopPolicy(stopPolicy);
RLMSyncManager *manager = [user.app syncManager];
__weak RLMSyncManager *weakManager = manager;
_config->error_handler = [weakManager](std::shared_ptr<SyncSession> errored_session, SyncError error) {
RLMSyncErrorReportingBlock errorHandler;
@autoreleasepool {
errorHandler = weakManager.errorHandler;
}
if (!errorHandler) {
return;
}
NSError *nsError = RLMTranslateSyncError(std::move(error));
if (!nsError) {
return;
}
RLMSyncSession *session = [[RLMSyncSession alloc] initWithSyncSession:errored_session];
dispatch_async(dispatch_get_main_queue(), ^{
errorHandler(nsError, session);
});
};
// Default to manual mode
_config->client_resync_mode = realm::ClientResyncMode(clientResetMode);
self.beforeClientReset = beforeResetBlock;
self.afterClientReset = afterResetBlock;

if (NSString *authorizationHeaderName = manager.authorizationHeaderName) {
_config->authorization_header_name.emplace(authorizationHeaderName.UTF8String);
if (!errorHandler) {
return;
}
if (NSDictionary<NSString *, NSString *> *customRequestHeaders = manager.customRequestHeaders) {
for (NSString *key in customRequestHeaders) {
_config->custom_http_headers.emplace(key.UTF8String, customRequestHeaders[key].UTF8String);
}
NSError *nsError = RLMTranslateSyncError(std::move(error));
if (!nsError) {
return;
}
RLMSyncSession *session = [[RLMSyncSession alloc] initWithSyncSession:errored_session];
dispatch_async(dispatch_get_main_queue(), ^{
errorHandler(nsError, session);
});
};

if (NSString *authorizationHeaderName = manager.authorizationHeaderName) {
config.authorization_header_name.emplace(authorizationHeaderName.UTF8String);
}
if (NSDictionary<NSString *, NSString *> *customRequestHeaders = manager.customRequestHeaders) {
for (NSString *key in customRequestHeaders) {
config.custom_http_headers.emplace(key.UTF8String, customRequestHeaders[key].UTF8String);
}
}
}

self.customFileURL = customFileURL;
return self;
- (instancetype)initWithUser:(RLMUser *)user
partitionValue:(nullable id<RLMBSON>)partitionValue {
if (self = [super init]) {
std::stringstream s;
s << RLMConvertRLMBSONToBson(partitionValue);
_config = std::make_unique<SyncConfig>([user _syncUser], s.str());
_path = [user pathForPartitionValue:_config->partition_value];
setDefaults(*_config, user);
}
return nil;
return self;
}

- (instancetype)initWithUser:(RLMUser *)user {
if (self = [super init]) {
_config = std::make_unique<SyncConfig>([user _syncUser], SyncConfig::FLXSyncEnabled{});
_path = [user pathForFlexibleSync];
setDefaults(*_config, user);
}
return self;
}

@end
18 changes: 5 additions & 13 deletions Realm/RLMSyncConfiguration_Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,14 @@ typedef RLM_CLOSED_ENUM(NSUInteger, RLMSyncStopPolicy) {

@interface RLMSyncConfiguration ()

// Flexible sync
- (instancetype)initWithUser:(RLMUser *)user;
// Partition-based sync
- (instancetype)initWithUser:(RLMUser *)user
partitionValue:(nullable id<RLMBSON>)partitionValue
stopPolicy:(RLMSyncStopPolicy)stopPolicy
clientResetMode:(RLMClientResetMode)clientResetMode
notifyBeforeReset:(nullable RLMClientResetBeforeBlock)beforeResetBlock
notifyAfterReset:(nullable RLMClientResetAfterBlock)afterResetBlock;

- (instancetype)initWithUser:(RLMUser *)user
stopPolicy:(RLMSyncStopPolicy)stopPolicy
enableFlexibleSync:(BOOL)enableFlexibleSync;

@property (nonatomic, readwrite) RLMSyncStopPolicy stopPolicy;
partitionValue:(nullable id<RLMBSON>)partitionValue;

// Internal-only APIs
@property (nullable, nonatomic) NSURL *customFileURL;

@property (nonatomic, readwrite) RLMSyncStopPolicy stopPolicy;
@property (nonatomic, readonly) BOOL enableFlexibleSync;

@end
Expand Down
Loading

0 comments on commit e0d0398

Please sign in to comment.