realm-swift icon indicating copy to clipboard operation
realm-swift copied to clipboard

Flexible Sync V2 QBS (Proposed 2)

Open jsflax opened this issue 2 years ago • 1 comments

This PR contains a complete new QBS API for Flexible Sync, intended to make flexible sync less confusing to the developer, this proposal use a query based subscription API, which makes use of async await to be able to add a subscription and bootstrap data from it.

let app = App(id: "my-app-id")
let user = try await app.login(credentials: .anonymous)
let realm = try await Realm(configuration: user.flexibleSyncConfiguration())

// You can subscribe and get a Result, using the async `function objects<>` API
let persons = try await realm.objects(SwiftPerson.self) // All documents for this object type
let dogs = try await realm.objects(SwiftDog.self, where: { $0.breed != "labradoodle" })
let birds = try await realm.objects(Bird.self, where: { $0.species.in(BirdSpecies.allCases) })

print(persons.count) //20

let newPerson = Person()
newPerson.age = 18
try realm.write {
    realm.add(newPerson)
}

// Updating a subscription is as easy as sub querying over the results
let newPerson = try await persons.where { $0.age > 18 }

// Unsubscribe will remove the values from the Realm and the Results collection and remove the subscription from the subscription set.
try await persons.unsubscribe()

// Reusing a Subscription is as easy as getting a `Results`  for the same query.
let persons = try await realm.objects(SwiftPerson.self, where: { $0.age > 12 })

// You can use unsubscribeAll to remove all subscriptions from the subscription set
try await realm.subscriptions.unsubscribeAll()

// Or you can remove them by type
try await realm.subscriptions.unsubscribeAll(ofType: Person.self)

SwiftUI You can use @ObservedResults to add a subscription and retrieve data from it, ObservedResults will subscribe to the query provided on the initialiser if this is a flexible sync realm app. We are adding a new property to @ObservedResultswhich includes a state value, this state will publish any subscription state changes to view.

public enum SubscriptionState {
    case pending //Subscription has been added and waiting for data to bootstrap.
    case error(Error) // An error has occurred while adding the subscription (client or server side)
    case completed // Data has been bootstrapped and query results updated.
}
@available(macOS 12.0, *)
struct ObservedQueryResultsStateView: View {
    @ObservedResults(Person.self, where: { $0.age > 18 && $0.firstName == ProcessInfo.processInfo.environment["firstName"]! })
    var persons

    var body: some View {
        VStack {
            switch $persons.state {
            case .pending:
                ProgressView()
            case .completed:
                List {
                    ForEach(persons) { person in
                        Text("\(person.firstName)")
                    }
                }
            case .error(let error):
                ErrorView(error: error)
                    .background(Color.red)
                    .transition(AnyTransition.move(edge: .trailing)).animation(.default)
            }
        }
    }
}

@available(macOS 12.0, *)
struct ObservedQueryResultsView: View {
    @ObservedResults(Person.self,  where: { $0.age >= 15 && $0.firstName == ProcessInfo.processInfo.environment["firstName"]! })
    var persons
    @State var searchFilter: String = ""

    var body: some View {
        VStack {
            if persons.isEmpty {
                ProgressView()
            } else {
                List {
                    ForEach(persons) { person in
                        HStack {
                            Text("\(person.firstName)")
                            Spacer()
                            Text("\(person.age)")
                        }
                    }
                }
            }
        }
        .onDisappear {
            Task {
                do {
                    try await $persons.unsubscribe()
                }
            }
        }
    }
}

jsflax avatar Mar 26 '22 15:03 jsflax

@jsflax I already made all the changes to this Proposal, this will need a review before MDBW.

dianaafanador3 avatar May 26 '22 16:05 dianaafanador3