Hi @Paolo_Manna
I just came across your example code, which was interesting to me. First off, before I go on, thanks for posting your example - I am sure it has and will continue to help many developers!
I compared your example to my setup and found in general we do a lot of the same. I did pick up your way of choosing an ‘asyncOpen’ or ‘sync’. Previously, I depended on tracking the progress on a Realm’s sync solely. Consequently, that could pause the user longer than needed in some cases, since I have some Realms not worth waiting for and benefit via ‘asyncOpen’.
I would like to bring some differences to your attention, that I felt were important for me and could be for some other developers too. If you don’t mind I would appreciate your thoughts - especially if I error-ed or have any oversights (thank you in advance). Below I have presented a question on your use of calling ‘realmSetupErrorHandler()
’ per Realm open.
In my usage, I like to know which Realm the ‘SyncSession’ is reporting on, for the ‘Error’ being handled. Therefore, I determine the Realm from the ‘SyncSession’ provided (which is the code I am providing). With that, I use such Realm in places thereafter. For example, sometimes I could use it to query before I back up the (reset-needing) Realm, and then merge later. Though for larger Realms it is better to query on a per Collection basis from the backed-up Realm. Merging gets tricky for Flexible Sync (FS), since it is based on query permissions and those results can change based on client-side usage (but that is a topic for another day). Luckily, for Partition-Based-Sync (PBS), it is straight forward. Oh yeah, I also pull the array of ‘ObjectTypes’ (e.g., ‘useThisRealmsConfig.objectTypes
’) to iterate through them for querying data, in order for merging into the new (downloaded) syncing Realm.
• I know for your example, it was testing 1 Realm (and 1 Schema) and therefore did NOT need to provide for additional Realms nor Schemas.
Some of my usage/differences to note:
• I am running multiple Realm-Apps on 1 client-side app. Therefore, I check for Flexible-Sync (FS) and Partition-Based-Sync (PBS) - this can also work in the future when both FS and PBS can be used in 1 Realm-App [].
• I have multiple Realms on PBS (i.e., per partition) and 1 Realm on FS (since FS currently works with only 1 Realm essentially).
• Since ‘.syncManager.errorHandler
’ is per Realm-App, I start it right after I open all the Realms (per Realm-App) in a single block. Since I’m running 2 Realm-Apps (per PBS & FS) I do this process twice - and only 2x (unless reloading Realm-App) and not per error being handled.
•• I noticed you do it per error handling (via Realm opens), is that something I need to change? - meaning (e.g.) is there some issue during errors that it is better re-pass it again?
/// SOME GENERAL NOTES.
/// I am running multiple Realm-Apps on 1 client-side app. Therefore, I test for Flexible-Sync (FS) and Partition-Based-Sync (PBS) - this can also work in the future when both FS and PBS can be used in 1 Realm-App [🤞].
/// I have multiple Realms on PBS (i.e., per partition) and 1 Realm on FS (since FS currently works with only 1 Realm essentially).
/// Since '`.syncManager.errorHandler`' is per Realm-App, I start it right after I open all the Realms (per Realm-App) in a single block. Since I'm running 2 Realm-Apps (per PBS & FS) I do this process twice - and only 2x (unless reload Realm-App) and not per error being handled.
/// My code setup is quite different, but I extracted and refactored my code for this part and to fit your example. I also named properties to be long in order to be verbose for any readers.
/// The changes could be entered here (line# 293) in your example (as of 2022-06-11). I would start by adding an unwrapped ‘SyncSession’. I renamed to use '`have`' prepended in the names too.
guard let haveSelf = self, let haveSession = session, let haveUser = haveSession.parentUser() else { return; }
guard let useThisRealmsSyncConfig = haveSession.configuration()
else {
// NOTE: CRASH in DEV, Error-Log in PROD. Reminder I started after opening a Realm.
fatalError();
}
print("During-TESTING-GOT:'useThisRealmsSyncConfig' - at this point we now know if this is 'Flexible-Sync'=='\(useThisRealmsSyncConfig.enableFlexibleSync)' - if 'true' then is 'FS'.")
let isFlexibleSyncEnabled = useThisRealmsSyncConfig.enableFlexibleSync
let useThisRealmsConfig: Realm.Configuration
if isFlexibleSyncEnabled {
useThisRealmsConfig = useThisRealmsSyncConfig.user.flexibleSyncConfiguration()
}
else {
guard let haveThisRealmsPartitionValue = useThisRealmsSyncConfig.partitionValue as? String
else {
// NOTE: This should not occur.
fatalError();
}
print("During-TESTING-GOT: 'haveThisRealmsPartitionValue', which is: '\(haveThisRealmsPartitionValue)'.")
useThisRealmsConfig = useThisRealmsSyncConfig.user.configuration(partitionValue: AnyBSON(haveThisRealmsPartitionValue), clientResetMode: .manual)
}
print("During-TESTING-GOT: 'useThisRealmsConfig', which its file-URL is: '\(String(describing: useThisRealmsConfig.fileURL))'.")
let useThisRealm: Realm
do {
useThisRealm = try Realm(configuration: useThisRealmsConfig)
}
catch let haveError as Error? {
fatalError("During-TESTING-GOT: an ERROR trying to get a 'Realm', here is the ERROR: '\(String(describing: haveError?.localizedDescription))'.");
}
print("During-TESTING-GOT: 'useThisRealm', which has: '\(useThisRealm.schema.objectSchema.count)' Schemas.")
/// This is provided to show how to get all objects to merge later. Also, based on the size of Realm you may want to do similar from the backed-up Realm and query on a per Collection basis. I wish there was an exposed property for last sync'd to prevent unnecessary loading here.
let allObjectTypesArray: [Object.Type] = (useThisRealm.configuration.objectTypes?.filter({ $0 is Object.Type }) ?? []) as! [Object.Type]
var mergeLaterArray: [ (Object.Type, [Object]) ] = [ ]
allObjectTypesArray.forEach({ mergeLaterArray.append(($0, Array(useThisRealm.objects($0)))) }) // may want to sort these too.
print("During-TESTING-GOT: this far! Now will test the current Realm (before backing-up) for querying before a Client-Reset. Here are values for: 'allObjectsArray' having '\(mergeLaterArray.count)' total Classes/Schemas && 'allObjectsArray' having '\(mergeLaterArray.compactMap({ $0.1 }).flatMap({ $0 }).count)' total objects across all Collections.")
/// back to your code
let syncError = error as! SyncError
var fileURL: URL?