realm / realm-swift

Realm is a mobile database: a replacement for Core Data & SQLite
https://realm.io
Apache License 2.0
16.31k stars 2.15k forks source link

Results and objects are not `isFrozen` after calling `freeze()` in a read-only realm #7878

Open joaocolaco opened 2 years ago

joaocolaco commented 2 years ago

Hi.

It seems the #7697 bug resurfaces when freezing a realm opened as read-only. In my case calling freeze() in a realm returns exactly the same realm (that also returns false to .isFrozen). Changing readOnly to true in the realm configuration makes freeze() work again.

Can this bug be fixed?

@dianaafanador3 has already done an repo test in https://github.com/realm/realm-swift/issues/7697#issuecomment-1178911563_

Originally posted by @joaocolaco in https://github.com/realm/realm-swift/issues/7697#issuecomment-1175366173

Edit with use case from https://github.com/realm/realm-swift/issues/7697#issuecomment-1179015318:

As for the use case freeze is also useful for querying the database in other threads, something that I need to do in my app (due to calls from SwiftUI and Swift async).

This particular database is in the Bundle Resources of the app so it shouldn't never be written. When the first version of the app was made the frozen functionality wasn't available so it was opened as read-only. When .frozen appeared I started to use it, but it didn't cross my mind that it would interfere with the read-only configuration until now.

Can I make a feature suggestion? Why not make all the read-only realms frozen? That would give "free" functionality and remove this sort of confusions.

dianaafanador3 commented 2 years ago

@tgoyne I don't know if this is the intended behaviour for a read only realm, and the use case is to be able to use the realm in another thread. I have the following test, which reproduce the issue,

func testFreezeReadOnlyRealm() throws {
        try autoreleasepool {
            let realm = try Realm()
            let frozenRealm = realm.freeze()
            XCTAssert(frozenRealm.isFrozen)
        }
        var configuration = Realm.Configuration.defaultConfiguration
        configuration.readOnly = true
        let realm = try Realm(configuration: configuration)
        let frozenRealm = realm.freeze()
        XCTAssert(frozenRealm.isFrozen) // This is failing
    }

Seems like the realm cannot be freeze because it doesn't have a version, but I don't know the intended behaviour behind it.

tgoyne commented 2 years ago

Read-only Realms should probably always just report isFrozen since they behave like frozen Realms and if we did that they'd become safe to use across threads.

joaocolaco commented 2 years ago

And that would also simplify a bit of my code (and whoever uses this functionality).

aehlke commented 1 year ago

What's the workaround for this bug? I don't quite understand but just realized after a day's effort that this is a library bug that I'm also hitting. Thanks

Ah the OP has a typo, readOnly should be false

dianaafanador3 commented 1 year ago

@jedelbo I think this will be a quick fix on OS, checking if the realm is readOnly and always return isFrozen true, then it would be safe to use the realm across threads.

aehlke commented 1 year ago

The workaround stopped working for me: now when I remove readOnly: true, it complains about not being able to create the .lock file inside the Bundle path.

aehlke commented 4 months ago

Bumping this issue - I still run into the above. Thanks