Prevent multiple apps from opening Realm File

Is there any way to prevent multiple apps from opening a Realm file under macOS ?

I was sure we used to get an exception if a second application tried to open a realm file that was already open by another application but this no longer seems to be the case.

We want to release a beta version but want to prevent the user from running the production application and the beta at the same time.

@Duncan_Groenewald So we definitely should still be throwing exceptions for multiprocess access. To be clear, the Realm SDK without sync does support multiprocess apps, that is why there is a .lock file, to manage mutations in an ACID compliant way. We do not support multiprocess apps for sync realms however, and here, you should be getting an exception.

If you are able to reproduce this please upload a sample app and we can sort this for you.

1 Like

Ah thanks for providing that clarification, didn’t realise there was a difference in behaviour.

It should be noted that we are using the Sync SDK but for the bulk of testing we are just connecting to a local file. Presumably the SDK will throw an exception when opening a Synced Realm from a second process but will allow opening a non-synced realm from multiple processes.

Did we miss this in the documentation somewhere ?

To share Realms between apps in the same iOS app group, you’ll need to specify a common location for the Realm. So something like this -

let fileURL = FileManager.default
    .containerURL(forSecurityApplicationGroupIdentifier: "")!
let config = Realm.Configuration(fileURL: fileURL)
let realm = try Realm(configuration: config)

Thanks, our app is a macOS Desktop app and we don’t need to share realms between apps or processes. We are planning to release a new beta version which can be installed at the same time as the production version but don’t want to allow them to be run at the same time.

@Ian_Ward - how can I catch this exception ? try Realm() does not seem to be throwing the exception so it goes through as an uncaught exception.

" uncaught exception of type realm::MultipleSyncAgents"

@Duncan_Groenewald So the error is thrown from the sync-client’s worker thread - so it cannot be caught. I’m not sure how the developer would handle this error, since presumably, opening the realm is necessary for the functioning of the app and likely should crash.

Well in our case it would be nice to be able to display a message to the user warning them that another application is already using the database and to close that application first if they wish to proceed.

You shouldn’t be killing the application from a worker thread - just send a message to the application saying you can’t continue and then exit the worker thread.

You probably shouldn’t be returning a Realm for the application to use until this has been checked anyway.

Similarly I think the SDK crashes the application with a fatal error if you try adding an object with a duplicate ID - again kind of weird to work like that - just return an error so the application can gracefully handle the situation. Its a pretty common problem with databases - even if the application checks for a duplicate ID prior to adding the object it is entirely possible that someone else might have added one between the time the check is performed and the call to add the object is made.

I am not aware that there is any way to link the check for duplicate ID with the call to add() as a transaction in Realm so the application should be left to handle the ‘duplicate key’ error rather than crashing the whole application. This isn’t a compile time check you can do but definitely a runtime check you should handle elegantly for the user.

Maybe I should raise this as a request on GitHub ? Would love to hear the arguments for simply crashing the application with a fatal error rather than returning an error.

@Duncan_Groenewald In the case of adding objects with primary keys, we have a default parameter named updatePolicy that allows users to choose how duplicate primary keys are handled – either by throwing an exception, updating the modified fields of the object with the matching primary keys, or by replacing all the fields. This circumvents most needs to handle a duplicate primary key.

1 Like