I’m running into issues with actors blocking each other from accessing Realms.
I have one Realm actor which I use for ALL writes: RealmBackgroundActor.
I also have TrackedItemsCacheActor which is only used to read from the same Realm. When I want to write, I switch to RealmBackgroundActor and open a Realm on that actor (and use thread safe references as necessary to pass them across, or directly if the objects are unmanaged before being written).
However when the below for-loop is running (it lasts for several minutes), all other attempts to open/init Realm on RealmBackgroundActor across the app will wait on a mutex/lock (per the stack traces) while this for-loop completes, even though the loop is on TrackedItemsCacheActor which is not used elsewhere in the application.
I expected to be able to do read/write operations on RealmBackgroundActor elsewhere in the app, without waiting for the below for-loop to finish, because it should only spend very short (well under a second) moments inside RealmBackgroundActor with a Realm that is opened and then deallocated repeatedly within the for-loop.
let firstWriteTask = Task { @TrackedItemsCacheActor in
for chunk in arrayOfUnmanagedRealmObjects.chunked(into: 40) {
try await Task { @RealmBackgroundActor in
let realm = try await Realm(actor: RealmBackgroundActor.shared)
try await realm.asyncWrite {
for trackedWord in chunk {
try Task.checkCancellation()
realm.add(trackedWord, update: .modified)
}
}
}.value
}
}
try await firstWriteTask.value
How can I have a long-running for-loop like the above, on its own actor, which doesn’t block Realm inits in RealmBackgroundActor elsewhere in the app?
edit: I just tried adding a long try? await Task.sleep(nanoseconds: 2_000_000_000)
sleep at the end of each loop, after the RealmBackgroundActor part finishes and back in the TrackedItemsCacheActor, and that worked to unblock other parts of the app… I originally tried a very short sleep which did not work. I’d love to know a better way to give enough breathing room to other parts of the app to open Realm on my RealmBackgroundActor actor, since guessing nanosecond thresholds seems very fragile. Indeed, it seems to sporadically work or break when I use e.g. 50ms instead of 2 seconds.