Skip to content

Conversation

dblythy
Copy link
Member

@dblythy dblythy commented Oct 1, 2025

Pull Request

Issue

Closes: #9086

Added LiveQuery query operation to execute queries through existing WebSocket subscriptions, eliminating separate REST API calls for data syncing.

Client SDK Changes Required:

  • Add result event type to LiveQuery constants

  • Handle result messages in WebSocket handler

  • Add query() method to subscription class

  • Add tests

Summary by CodeRabbit

  • New Features

    • LiveQuery supports on-demand read queries: subscribers can request results with where filtering and per-subscription field selection; results respect session-based access and triggers.
  • Bug Fixes

    • Improved error handling and reporting for missing clients or subscriptions and related query failures.
  • Tests

    • Added comprehensive end-to-end tests for query operations: successful flows, field filtering, where constraints, trigger integration, and error paths.

Copy link

parse-github-assistant bot commented Oct 1, 2025

🚀 Thanks for opening this pull request!

Copy link

coderabbitai bot commented Oct 1, 2025

📝 Walkthrough

Walkthrough

Adds a LiveQuery "query" operation: request schema update, server-side handler to execute finds and return results, client API to push query results, and tests validating result delivery, field selection, where constraints, and error paths.

Changes

Cohort / File(s) Summary
Tests: ParseLiveQuery query suite
spec/ParseLiveQueryQuery.spec.js
New test suite exercising LiveQuery query requests: success paths, multi-object results, keys-based field filtering, where constraints, missing clientId/subscription error reporting, and helper mocks for clients/subscriptions.
LiveQuery Client: push result API
src/LiveQuery/Client.js
Adds pushResult (bound to _pushQueryResult) which builds op: 'result' messages including clientId, installationId, and requestId, maps results through _toJSONWithFields per-subscription keys, and sends via existing pushResponse.
LiveQuery Server: query op handling
src/LiveQuery/ParseLiveQueryServer.ts
Adds handling for op: 'query' and new _handleQuery method: validates client and subscription, resolves auth (subscription.sessionToken
Request Schema: query op
src/LiveQuery/RequestSchema.js
Adds query operation schema and exposes RequestSchema.query, registering op: 'query' with numeric requestId in supported request schemas.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant SDK as LiveQuery Client SDK
  participant WS as WebSocket Server
  participant Srv as ParseLiveQueryServer
  participant Sub as Subscription Registry
  participant DB as Data Store

  rect rgba(230,240,255,0.4)
    note left of SDK: client sends a query tied to a subscriptionId
  end

  SDK->>WS: { op: "query", requestId, id: subscriptionId, where, keys }
  WS->>Srv: route "query" request
  Srv->>Sub: lookup subscription(subscriptionId)
  alt subscription found
    Srv->>Srv: resolve auth (subscription.sessionToken || client.sessionToken || master)
    Srv->>DB: find(className, where, keys)
    DB-->>Srv: results[]
    Srv->>WS: push { op: "result", requestId, clientId, installationId, results }
    WS-->>SDK: deliver "result"
  else subscription missing
    Srv->>WS: push error { op: "error", requestId, ... }
    WS-->>SDK: deliver error
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The pull request description omits the required “## Approach” section heading and does not clearly describe the implementation strategy under that heading, and it leaves the documentation and other task checkboxes in an incomplete state. Please add a “## Approach” section to detail the implementation changes, update or remove the documentation and other task entries to reflect what has been completed, and ensure all required template sections are present and accurate.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title "feature: run query via livequery" clearly and concisely reflects the primary change of introducing a LiveQuery query operation and aligns with the main intent of the pull request.
Linked Issues Check ✅ Passed The changes implement the core linked-issue requirements by adding a server‐side “query” LiveQuery operation with authentication, where and key filtering, error handling, and corresponding tests that verify initial result delivery as specified in issue #9086.
Out of Scope Changes Check ✅ Passed All modified files and logic are directly related to the new LiveQuery query operation and its test suite, with no unrelated or extraneous changes introduced.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@parseplatformorg
Copy link
Contributor

parseplatformorg commented Oct 1, 2025

🎉 Snyk checks have passed. No issues have been found so far.

security/snyk check is complete. No issues have been found. (View Details)

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 1, 2025
coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 1, 2025
Copy link

codecov bot commented Oct 1, 2025

Codecov Report

❌ Patch coverage is 56.60377% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.44%. Comparing base (389de84) to head (e3a169c).

Files with missing lines Patch % Lines
src/LiveQuery/ParseLiveQueryServer.ts 63.63% 15 Missing and 1 partial ⚠️
src/LiveQuery/Client.js 12.50% 7 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            alpha    #9864      +/-   ##
==========================================
- Coverage   93.02%   92.44%   -0.59%     
==========================================
  Files         187      187              
  Lines       15096    15149      +53     
  Branches      174      183       +9     
==========================================
- Hits        14043    14004      -39     
- Misses       1041     1128      +87     
- Partials       12       17       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
spec/ParseLiveQueryQuery.spec.js (1)

6-19: Remove unnecessary done callback from synchronous beforeEach.

The beforeEach function is synchronous but declares a done parameter and calls it. Jasmine only requires the done callback for asynchronous setup. This adds unnecessary overhead.

Apply this diff:

-  beforeEach(function (done) {
+  beforeEach(function () {
     Parse.CoreManager.getLiveQueryController().setDefaultLiveQueryClient(null);
     // Mock ParseWebSocketServer
     const mockParseWebSocketServer = jasmine.createSpy('ParseWebSocketServer');
     jasmine.mockLibrary(
       '../lib/LiveQuery/ParseWebSocketServer',
       'ParseWebSocketServer',
       mockParseWebSocketServer
     );
     // Mock Client pushError
     const Client = require('../lib/LiveQuery/Client').Client;
     Client.pushError = jasmine.createSpy('pushError');
-    done();
   });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f31285 and e3a169c.

📒 Files selected for processing (1)
  • spec/ParseLiveQueryQuery.spec.js (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-04-30T19:31:35.344Z
Learnt from: RahulLanjewar93
PR: parse-community/parse-server#9744
File: spec/ParseLiveQuery.spec.js:0-0
Timestamp: 2025-04-30T19:31:35.344Z
Learning: In the Parse Server codebase, the functions in QueryTools.js are typically tested through end-to-end behavior tests rather than direct unit tests, even though the functions are exported from the module.

Applied to files:

  • spec/ParseLiveQueryQuery.spec.js
🧬 Code graph analysis (1)
spec/ParseLiveQueryQuery.spec.js (2)
src/LiveQuery/RequestSchema.js (1)
  • query (152-163)
spec/helper.js (1)
  • reconfigureServer (171-205)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: PostgreSQL 17, PostGIS 3.5
  • GitHub Check: PostgreSQL 15, PostGIS 3.4
  • GitHub Check: PostgreSQL 16, PostGIS 3.5
  • GitHub Check: MongoDB 8, ReplicaSet
  • GitHub Check: PostgreSQL 15, PostGIS 3.5
  • GitHub Check: Redis Cache
  • GitHub Check: Node 20
  • GitHub Check: Node 18
  • GitHub Check: MongoDB 7, ReplicaSet
  • GitHub Check: PostgreSQL 15, PostGIS 3.3
  • GitHub Check: MongoDB 6, ReplicaSet
  • GitHub Check: Docker Build
🔇 Additional comments (7)
spec/ParseLiveQueryQuery.spec.js (7)

21-27: LGTM! Proper async cleanup.

The cleanup properly closes LiveQuery clients and restores mocked libraries, ensuring test isolation.


29-35: LGTM! Well-structured test helper.

The helper cleanly creates and registers a mock client with a spy for result verification.


37-64: LGTM! Comprehensive subscription setup helper.

The helper correctly establishes subscription state on both server and client sides, mirroring the production subscription structure.


124-150: LGTM! Comprehensive error handling coverage.

These tests properly validate error paths when clientId is missing or subscription doesn't exist, ensuring robust error handling.


163-167: Verify serverURL configuration in field filtering and where constraint tests.

Similar to the first test, these tests use serverURL: 'http://localhost:1337/parse' while reconfigureServer likely uses a different port. Ensure this doesn't cause query execution failures.

The verification script from the earlier comment applies here as well.

Also applies to: 224-228


152-211: LGTM! Field filtering validation is thorough.

The test correctly validates that the keys parameter restricts returned fields, checking both included and excluded fields.


213-270: LGTM! Where clause filtering is properly tested.

The test validates that query constraints are correctly applied, returning only matching objects.

Comment on lines +76 to +81
const { ParseLiveQueryServer } = require('../lib/LiveQuery/ParseLiveQueryServer');
const parseLiveQueryServer = new ParseLiveQueryServer({
appId: 'test',
masterKey: 'test',
serverURL: 'http://localhost:1337/parse'
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify serverURL configuration matches test setup.

The ParseLiveQueryServer is configured with serverURL: 'http://localhost:1337/parse', but the test uses reconfigureServer which typically runs on a different port. If the query operation makes REST calls to Parse Server, this mismatch could cause connection failures.

Check if the serverURL should use the same port as the reconfigured server:


🏁 Script executed:

#!/bin/bash
# Find how reconfigureServer sets the port for Parse Server
rg -nP -A5 'reconfigureServer.*=.*async' spec/helper.js

# Check if _handleQuery makes REST calls using serverURL
ast-grep --pattern '_handleQuery($$$) {
  $$$
}'

Length of output: 279


🏁 Script executed:

#!/bin/bash
# Locate the ParseLiveQueryServer class definition
rg -nP -C3 'class\s+ParseLiveQueryServer' --glob '*.js'

# Inspect the _handleQuery method implementation
rg -nP -C3 '_handleQuery' --glob '*.js'

# Look for usage of serverURL within the file
rg -nP 'serverURL' -C3 --glob '*.js'

Length of output: 112115


🏁 Script executed:

#!/bin/bash
# Locate the ParseLiveQueryServer source
grep -R "class ParseLiveQueryServer" -n lib/LiveQuery/ParseLiveQueryServer.js

# Inspect constructor for serverURL usage
grep -R "constructor" -n lib/LiveQuery/ParseLiveQueryServer.js -A5

# Inspect query handler implementation
grep -R "_handleQuery" -n lib/LiveQuery/ParseLiveQueryServer.js -A5

# Check for directAccess default and serverURL fallback
grep -R "directAccess" -n lib/LiveQuery/ParseLiveQueryServer.js -A3

Length of output: 283


🏁 Script executed:

#!/bin/bash
# List top-level directories to locate code structure
ls -1

# Search for ParseLiveQueryServer definition anywhere in the repo
rg -nP 'class\s+ParseLiveQueryServer' -g '*.js'

# If found, inspect the constructor and _handleQuery methods
rg -nP --context 5 'constructor\s*\(' -g '*ParseLiveQueryServer.js'
rg -nP --context 5 '_handleQuery\s*\(' -g '*ParseLiveQueryServer.js'

Length of output: 650


#!/bin/bash
# Dynamically locate the ParseLiveQueryServer implementation
file=$(grep -R "class ParseLiveQueryServer" -l src | head -1)
echo "Inspecting $file"
# Show constructor to see how serverURL is stored
grep -nE 'constructor' -C3 "$file"
# Show how _handleQuery uses serverURL or directAccess
grep -nE '_handleQuery' -C3 "$file"
# Show any references to serverURL in this class
grep -nE 'serverURL' -C3 "$file"

🏁 Script executed:

#!/bin/bash
# Search for ParseLiveQueryServer implementation in TypeScript sources
rg -nP 'class\s+ParseLiveQueryServer' -g 'src/**/*.ts'

# Print the file path(s)
rg -lP 'class\s+ParseLiveQueryServer' -g 'src/**/*.ts'

# Inspect the found file
FILE=$(rg -lP 'class\s+ParseLiveQueryServer' -g 'src/**/*.ts' | head -1)
echo "Inspecting $FILE"
grep -nE 'constructor' -C3 "$FILE"
grep -nE '_handleQuery' -C3 "$FILE"
grep -nE 'serverURL' -C3 "$FILE"

Length of output: 1789


🏁 Script executed:

#!/bin/bash
sed -n '1000,1100p' src/LiveQuery/ParseLiveQueryServer.ts

Length of output: 3677


🏁 Script executed:

#!/bin/bash
sed -n '1,200p' src/LiveQuery/ParseLiveQueryServer.ts

Length of output: 7315


Replace hard-coded serverURL in query tests
In spec/ParseLiveQueryQuery.spec.js (around line 76), you’re instantiating ParseLiveQueryServer with serverURL: 'http://localhost:1337/parse', but the test helper reconfigures Parse Server on port 8378 with mount /1. This mismatch causes _handleQuery to point at the wrong endpoint. Use the helper’s serverURL (or Parse.serverURL) instead so LiveQueryServer and the test Parse Server align.

🤖 Prompt for AI Agents
In spec/ParseLiveQueryQuery.spec.js around lines 76 to 81, the
ParseLiveQueryServer is instantiated with a hard-coded serverURL
'http://localhost:1337/parse' which mismatches the test helper’s Parse Server
(port 8378, mount '/1'), causing _handleQuery to target the wrong endpoint;
replace the hard-coded URL with the helper-provided server URL (e.g., use the
helper’s serverURL variable or Parse.serverURL) so the ParseLiveQueryServer and
the test Parse Server use the same base URL and mount.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow to run queries through LiveQueryClient
2 participants