realm / realm-swift

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

@AutoOpen does not open realm offline #7986

Closed sonisan closed 1 year ago

sonisan commented 2 years ago

How frequently does the bug occur?

All the time

Description

I have been trying to use the @AutoOpen property wrapper to open a realm with a flexible sync configuration during the app initialisation. If the device is offline, the realm is blocked in .connecting state and is never opened. It is working as intended if the device is online.

Stacktrace & log output

Configuration created
connecting
connecting
connecting

Can you reproduce the bug?

Yes, always

Reproduction Steps

  1. If in memory, kill the app from the app switcher
  2. Open the app
import SwiftUI
import RealmSwift

@main
struct MyApp: SwiftUI.App {
    var body: some Scene {

        WindowGroup {
            let app: RealmSwift.App? = App(id: Constants.APP_ID)
            if let app = app {
                SyncContentView()
                    .environmentObject(app)
            }
        }
    }
}

struct SyncContentView: View {
    @EnvironmentObject var app: RealmSwift.App

    var body: some View {
        if let currentRealmUser = app.currentUser {
            let configuration = currentRealmUser.flexibleSyncConfiguration(initialSubscriptions: { subs in

                if subs.first(named: "report") == nil {
                    print("Adding report subscription...")
                    subs.append(QuerySubscription<Report>(name: "report") {
                        $0.ownedBy == "ADMIN"
                    })
                }
                // adding other subscriptions...
            })
            let _ = print("Configuration created")
            OpenSyncedRealmView()
                .environment(\.realmConfiguration, configuration)

        } else {
            AuthenticationView()
        }
    }
}

    struct OpenSyncedRealmView: View {
        @EnvironmentObject var app: RealmSwift.App

        @AutoOpen(appId: Constants.APP_ID) var autoOpen

        var body: some View {
            let user = app.currentUser
            let _ = print(autoOpen)

            switch autoOpen {
            case .open(let realm):
                let _ = print("--- REALM OPENED ---")
                let currentUser = realm.objects(User.self).where({try! $0._id == ObjectId(string: user!.id)}).first!
                let realmManager = RealmManager(app: app, realm: realm)
                TabView {
                    LibraryView(currentUser: currentUser)
                            .tabItem {
                                Label("Library", systemImage: "books.vertical")
                            }

                    ChartsView()
                            .tabItem {
                                Label("Charts", systemImage: "chart.bar.xaxis")
                            }                   
                }
                .environmentObject(realmManager)
                .environment(\.realm, realm)
            case .connecting:
                ProgressView("Logging in...")
            case .waitingForUser:
                ProgressView("Waiting for user to log in...")
            case .progress:
                ProgressView("Syncing your data...")
            case .error(let error):
                ErrorView(error: error)
            }
        }
}

Version

Realm 10.31.0

What SDK flavour are you using?

MongoDB Realm (i.e. Sync, auth, functions)

Are you using encryption?

No, not using encryption

Platform OS and version(s)

macOS 12.6

Build environment

Xcode version: 14.0 Dependency manager and version: ...

dianaafanador3 commented 1 year ago

Fixed in this PR https://github.com/realm/realm-swift/issues/8029

Jonovono commented 1 year ago

Hi @dianaafanador3 Are we sure this is fixed? I am using AutoOpen like so:

    @AutoOpen(
        appId: AtlasClient.shared.appId,
        timeout: 5000) var autoOpen

    @State var user: RealmSwift.User
    let onboardData: OnboardData?

    @Environment(\.realmConfiguration) private var config

    var body: some View {
        switch autoOpen {
        case .connecting:
            LoadingScreen()
        case .waitingForUser:
            LoadingScreen()
        case .open(let realm):
            RootContainer(shopper: {
                if realm.objects(Shopper.self).count == 0 {
                    try! realm.write {
                        let newShopper = Shopper()

//                        newShopper.firebaseUserId = FirebaseClient.shared.currentUserId()!
                        realm.add(newShopper)
                    }
                }
                return realm.objects(Shopper.self).first!
            }()).environment(\.realm, realm)

        case .progress(let progress):
            LoadingScreen()
        case .error(let error):
            ErrorScreenView()
                .onAppear {
                    ErrorLoggingService.shared.recordError(error)
                    print("Error", error)
                }
        }
    }

But when I go offline I get the error "Failed to connect to sync. Host not found (authoritative)"

dvhull commented 9 months ago

I am also getting this error still did you ever find a work around??

Hi @dianaafanador3 Are we sure this is fixed? I am using AutoOpen like so:

    @AutoOpen(
        appId: AtlasClient.shared.appId,
        timeout: 5000) var autoOpen

    @State var user: RealmSwift.User
    let onboardData: OnboardData?

    @Environment(\.realmConfiguration) private var config

    var body: some View {
        switch autoOpen {
        case .connecting:
            LoadingScreen()
        case .waitingForUser:
            LoadingScreen()
        case .open(let realm):
            RootContainer(shopper: {
                if realm.objects(Shopper.self).count == 0 {
                    try! realm.write {
                        let newShopper = Shopper()

//                        newShopper.firebaseUserId = FirebaseClient.shared.currentUserId()!
                        realm.add(newShopper)
                    }
                }
                return realm.objects(Shopper.self).first!
            }()).environment(\.realm, realm)

        case .progress(let progress):
            LoadingScreen()
        case .error(let error):
            ErrorScreenView()
                .onAppear {
                    ErrorLoggingService.shared.recordError(error)
                    print("Error", error)
                }
        }
    }

But when I go offline I get the error "Failed to connect to sync. Host not found (authoritative)"