realm / realm-swift

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

Allow addProgressNotification when using async initializer #7763

Open rowungiles opened 2 years ago

rowungiles commented 2 years ago

Problem

When using let realm = try await Realm(configuration: configuration, downloadBeforeOpen: .once) I'd like to track the download progress of that sync.

Looking at the async initializer that isn't possible as task is hidden (as is callbackQueue):

rlmRealm = try await withCheckedThrowingContinuation { continuation in
                RLMRealm.asyncOpen(with: configuration.rlmConfiguration, callbackQueue: .main) { (realm, error) in
                    if let error = error {
                        continuation.resume(with: .failure(error))
                    } else {
                        continuation.resume(with: .success(realm!))
                    }
                }
            }

Solution

With a goal of minimising design changes, the smallest change I can think of is passing in a block and a queue to set internally on the task returned from RLMRealm.asyncOpen.

@MainActor
    public init(configuration: Realm.Configuration = .defaultConfiguration,
                downloadBeforeOpen: OpenBehavior = .never,
                callbackQueue: DispatchQueue = .main,
                block: @escaping (SyncSession.Progress) -> Void = nil) async throws {
        var rlmRealm: RLMRealm?
        switch downloadBeforeOpen {
        case .never:
            break
        case .once:
            if !Realm.fileExists(for: configuration) {
                fallthrough
            }
        case .always:
            rlmRealm = try await withCheckedThrowingContinuation { continuation in
                let task = RLMRealm.asyncOpen(with: configuration.rlmConfiguration, callbackQueue: callbackQueue) { (realm, error) in
                    if let error = error {
                        continuation.resume(with: .failure(error))
                    } else {
                        continuation.resume(with: .success(realm!))
                    }
                }
                task.addProgressNotification(queue: callbackQueue) { progress in
                        block(progress)
                }
            }
        }
        if rlmRealm == nil {
            rlmRealm = try RLMRealm(configuration: configuration.rlmConfiguration)
        }
        self.init(rlmRealm!)
    }

How important is this improvement for you?

Would be a major improvement

tcollins590 commented 1 year ago

I'm running into the same issue. I'm about to move away from Async/Await for opening the realm until I can track downloads.

dianaafanador3 commented 1 year ago

Hi @captn590 @rowungiles Thanks for reaching. We are taking a look at this and discussing this with the team, so we can come up with the best solution (API) for this.

bdkjones commented 7 months ago

Was there ever a resolution here, or is this another one of those, "we'll get back to you in 7 years to tell you we still don't have an answer" issues?

AsyncOpen can take a long time to "bootstrap changesets" and not being able to show progress to the user is very frustrating.

Please fill this hole--enough talking; get the feature shipped!

nirinchev commented 7 months ago

That is fair criticism. I'll see if we can add it as part of the project that adds support for bootstrap progress notifications.