Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flexible Sync V2 QBS (Proposed 2) #7722

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Conversation

jsflax
Copy link
Contributor

@jsflax jsflax commented Mar 26, 2022

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()
                }
            }
        }
    }
}

@cla-bot cla-bot bot added the cla: yes label Mar 26, 2022
@dianaafanador3 dianaafanador3 changed the title Add QBS API Proposal 3 Flexible Sync B2 QBS (Proposed 2) May 25, 2022
@dianaafanador3 dianaafanador3 changed the title Flexible Sync B2 QBS (Proposed 2) Flexible Sync V2 QBS (Proposed 2) May 26, 2022
@dianaafanador3 dianaafanador3 assigned jsflax and unassigned jsflax May 26, 2022
@dianaafanador3
Copy link
Collaborator

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

@dianaafanador3 dianaafanador3 marked this pull request as ready for review May 26, 2022 16:01
@dianaafanador3 dianaafanador3 force-pushed the jf/qbs-api-proposal-3 branch 3 times, most recently from 7251ac9 to 46f5016 Compare June 15, 2022 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants