parse-community / Parse-SDK-JS

The JavaScript SDK for Parse Platform
https://parseplatform.org
Apache License 2.0
1.31k stars 599 forks source link

Allow to run queries through LiveQueryClient (Parse Server issue #9086) #2114

Open messagenius-admin opened 2 months ago

messagenius-admin commented 2 months ago

It should be possible to run Queries through a LiveQueryClient, and/or to request query results along with LiveQuery subscription to enable syncing collections and subscribing to LiveQueries with a single WebSocket connection.

A Parse Server issue with detailed information has been created here: https://github.com/parse-community/parse-server/issues/9086. However, this feature requires development on both client and server.

Possible Alternative 1: Get query results leveraging the subscription

subscription.on('result', task => tasks[task.id] = task);
subscription.find(); // or subscription.first(); or getResults() or runQuery(), or any other naming that makes sense.

Possible Alternative 2: Allow running any query from a LiveQueryClient. This potentially enables developers to run queries through WebSocket, detached from a subscription.

const client = new LiveQueryClient({ ... });
const querySubscription = client.querySubscribe(query);
querySubscription.on('result', task => tasks[task.id] = task);

Ideally, both alternatives 1 and 2 should be developed, with one serving as a shortcut for the other, similar to how currently a subscription can be run with or without an explicit liveQueryClient.

EDIT Apr 30: Consider running all requests through WebSocket, including Queries, Saves, Cloud Functions, and all CRUD operations.

parse-github-assistant[bot] commented 2 months ago

Thanks for opening this issue!

dplewis commented 2 months ago

@messagenius-admin I think the easiest solution would be to return the results of the query. This is an improved version of Alt 1.

querySubscription.on('results', results => { tasks = results; });

Once a results event is listened to the initial query runs, pin objects to the Local Datastore and return the results. If a create, update or delete event triggers we can update the Local Datastore to be in sync with the collections and query.fromLocalDatastore() to return the results.

The update event already updates the Local Datastore as well as Parse.Object.save.

This wouldn't require a server update.

messagenius-admin commented 2 months ago

@dplewis, the goal is to sync an App with the Server also when the app is re-opened after being killed, shut down or restored from the background. In such cases, even if you re-subscribe to the LiveQuery, there may be a gap between the objects stored in your local storage, and the server.

You need a Query to get all objects created or updated after the last time you opened the app, and you need to merge query results with your local copies.

The focus of this issue/improvement is to enable querying Parse Server via the Websocket connection, rather than solely relying on REST API calls.

The full scenario is described in the parent issue (https://github.com/parse-community/parse-server/issues/9086).

dplewis commented 2 months ago

@messagenius-admin I see what you're saying, my solution would be more for offline apps, syncing the local storage after page load, re-open, shut down etc.

In Alternative 1 if I call subscription.find() this would trigger the server to query and send the results over the Websocket connection?

const results = await subscription.find() or subscription.on('result', callback)

messagenius-admin commented 2 months ago

@dplewis Yes, the goal is to avoid REST API calls when a WebSocket connection is in place.

I have updated the Issue description to consider running all CRUD operations and Cloud Functions calls through Websocket.