Skip to content

Conversation

@dblythy
Copy link
Member

@dblythy dblythy commented Oct 1, 2025

Pull Request

Issue

parse-community/parse-server#9864

Closes: #2114

Approach

Tasks

  • Add tests
  • Add changes to documentation (guides, repository pages, code comments)

Summary by CodeRabbit

  • New Features

    • Subscriptions can now request query results on-demand and receive batched "result" events containing parsed objects.
    • Subscriptions may be linked to the live client to enable sending queries.
  • Tests

    • Added coverage for handling "result" events, missing class names in payloads, and the on-demand query flow.
  • Documentation

    • Type definitions and JSDoc updated to document the new subscription client linkage, constructor signature, and the find/result API.

@parse-github-assistant
Copy link

🚀 Thanks for opening this pull request!

@coderabbitai
Copy link

coderabbitai bot commented Oct 1, 2025

Warning

Rate limit exceeded

@dblythy has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 5 minutes and 36 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between b0aa375 and fae5512.

📒 Files selected for processing (1)
  • types/LiveQueryClient.d.ts (1 hunks)
📝 Walkthrough

Walkthrough

Adds QUERY op and RESULT event handling to LiveQueryClient, passes client reference into LiveQuerySubscription, implements subscription.find() to send a QUERY via WebSocket, maps RESULT payloads to ParseObject instances (setting className when missing) and emits them on the subscription, and updates types and tests accordingly.

Changes

Cohort / File(s) Summary
LiveQuery client ops & events
src/LiveQueryClient.ts
Adds OP_TYPES.QUERY, OP_EVENTS.RESULT, and SUBSCRIPTION_EMMITER_TYPES.RESULT; strengthens typings (constructor, on/emit, generateInterval); constructs subscriptions with a client reference; handles incoming RESULT messages by mapping data.results to ParseObject (assign className from subscription query if missing) and emits 'result' on the subscription.
Subscription client plumbing & query API
src/LiveQuerySubscription.ts
Adds public client field; updates constructor to accept optional client; adds find() which waits for client.connectPromise and sends a QUERY operation over the client's socket using the subscription id as requestId (no-op when client absent).
Type declarations
types/LiveQuerySubscription.d.ts
Declares client: any; updates constructor signature to (..., client?: any); adds find(): void with documentation indicating results are delivered via the 'result' event.
Tests for result flow and find()
src/__tests__/LiveQueryClient-test.js
Adds tests confirming LiveQuerySubscription.prototype.find exists; verifies subscription find() sends correct QUERY payload; adds tests simulating WebSocket RESULT messages (with and without className) and asserting proper mapping and 'result' emission.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor App as Application
  participant Sub as LiveQuerySubscription
  participant LQC as LiveQueryClient
  participant WS as WebSocket
  participant PS as ParseServer

  App->>Sub: subscription.find()
  alt client attached
    Sub->>LQC: await connectPromise
    LQC->>WS: send OP_TYPES.QUERY { requestId: sub.id, query, sessionToken }
    WS->>PS: forward QUERY
    PS-->>WS: RESULT { requestId, results:[...] }
    WS-->>LQC: message(OP_EVENTS.RESULT, { requestId, results })
    LQC->>LQC: map results -> ParseObject (set className if missing)
    LQC->>Sub: emit('result', [ParseObject,...])
    Sub-->>App: 'result' event with mapped results
  else no client
    Sub-->>App: find() is no-op
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Potential focus areas:

  • Correctness of RESULT -> ParseObject mapping and className assignment.
  • Timing around client.connectPromise, socket state, and error handling in find().
  • Memory/lifecycle implications of storing client on subscriptions.
  • Type signature updates in LiveQueryClient constructor and on/emit wrappers to ensure compatibility with consumers.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
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 (4 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "feature: add subscription.find" is concise, specific, and clearly describes the main change in the changeset. It accurately summarizes the primary feature being introduced - a new find() method on LiveQuerySubscription that enables executing queries through a live query subscription. The title is not vague or misleading and a developer reviewing the repository history would understand that this PR adds subscription query functionality.
Linked Issues Check ✅ Passed The linked issue #2114 outlines two proposed approaches: Alternative 1 adds methods like subscription.find() to return query results, and Alternative 2 allows running queries independently through a LiveQueryClient. This PR implements Alternative 1 completely, adding the find() method to LiveQuerySubscription and enabling result event delivery through the WebSocket connection. The implementation adds proper RESULT event handling, type support, comprehensive tests, and TypeScript declarations. Alternative 2 (client.querySubscribe) is not implemented, but the issue uses "and/or" language indicating either approach satisfies the core requirement of enabling query execution through the WebSocket connection.
Out of Scope Changes Check ✅ Passed All code changes are directly aligned with the objective in issue #2114 of enabling query results through subscriptions. The changes include: adding QUERY operation and RESULT event types to support the protocol, enhancing type annotations for better development experience, implementing WebSocket result message handling, adding the new find() method and client reference to LiveQuerySubscription, and comprehensive test coverage. No changes appear to address unrelated concerns or drift outside the scope of implementing subscription-based query execution.
Description Check ✅ Passed The PR description fills out most of the required template sections: it includes the security reporting and license links, provides links to related issues (parse-community/parse-server#9864 and closes #2114), and includes the tasks checklist. However, the Approach section is completely empty, leaving no explanation of what changes were made or why. This is a significant omission that reduces clarity about the implementation details, though the critical linking information and task checklist are present.

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.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@codecov
Copy link

codecov bot commented Oct 1, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.88%. Comparing base (17e2a77) to head (fae5512).
⚠️ Report is 44 commits behind head on alpha.

Additional details and impacted files
@@             Coverage Diff             @@
##             alpha    #2735      +/-   ##
===========================================
- Coverage   100.00%   99.88%   -0.12%     
===========================================
  Files           63       64       +1     
  Lines         6185     6233      +48     
  Branches      1456     1492      +36     
===========================================
+ Hits          6185     6226      +41     
- Misses           0        7       +7     

☔ 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: 2

🧹 Nitpick comments (3)
types/LiveQuerySubscription.d.ts (2)

92-92: Consider stronger typing for the client field.

The client field is currently typed as any, which loses type safety. While a direct LiveQueryClient type would create a circular dependency, consider defining a minimal interface or using import type to preserve type information without runtime circularity.

Example approach:

+import type LiveQueryClient from './LiveQueryClient';
+
 declare class LiveQuerySubscription {
     id: string | number;
     query: ParseQuery;
     sessionToken?: string;
     subscribePromise: any;
     unsubscribePromise: any;
     subscribed: boolean;
-    client: any;
+    client?: LiveQueryClient;
     emitter: EventEmitter;
     on: EventEmitter['on'];
     emit: EventEmitter['emit'];
-    constructor(id: string | number, query: ParseQuery, sessionToken?: string, client?: any);
+    constructor(id: string | number, query: ParseQuery, sessionToken?: string, client?: LiveQueryClient);

Also applies to: 96-96


103-107: Enhance JSDoc to document preconditions.

The documentation for find() should clarify what happens when client is not set, and whether callers need to wait for connection before calling.

 /**
  * Execute a query on this subscription.
  * The results will be delivered via the 'result' event.
+ * Note: This method requires a client to be set and will only send the query
+ * after the client's connection promise resolves.
  */
 find(): void;
src/__tests__/LiveQueryClient-test.js (1)

1155-1184: LGTM! Consider adding edge case test.

The test correctly verifies that subscription.find() sends a properly formatted query message with the correct op and requestId. The test appropriately waits for the connection promise before calling find().

Consider adding a test for the edge case where find() is called when client is not set or before connection is established:

it('find() does nothing when client is not set', () => {
  const subscription = new LiveQuerySubscription(1, new ParseQuery('Test'));
  expect(() => subscription.find()).not.toThrow();
});
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17e2a77 and 7000301.

📒 Files selected for processing (4)
  • src/LiveQueryClient.ts (5 hunks)
  • src/LiveQuerySubscription.ts (2 hunks)
  • src/__tests__/LiveQueryClient-test.js (3 hunks)
  • types/LiveQuerySubscription.d.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/__tests__/LiveQueryClient-test.js (2)
src/__tests__/ParseQuery-test.js (2)
  • LiveQuerySubscription (35-35)
  • ParseQuery (34-34)
src/__tests__/ParseLiveQuery-test.js (2)
  • LiveQuerySubscription (16-16)
  • ParseQuery (15-15)
⏰ 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). (2)
  • GitHub Check: build (Node 20, 20.15.1)
  • GitHub Check: build (Node 18, 18.20.4)
🔇 Additional comments (8)
src/LiveQueryClient.ts (4)

24-24: LGTM!

The addition of the QUERY operation type follows the existing pattern and is correctly placed.


38-38: LGTM!

The RESULT event type addition is correctly placed and follows the existing pattern.


58-58: LGTM!

The RESULT emitter type addition is correctly placed and follows the existing pattern.


218-218: LGTM!

Passing the client instance to the subscription constructor enables subscription.find() to send messages over the WebSocket. This is essential for the new query execution feature.

src/__tests__/LiveQueryClient-test.js (3)

1-1: LGTM!

Unmocking LiveQuerySubscription and importing it directly is necessary to test the new find() method and verify prototype behavior. This follows the same pattern used in other test files.

Also applies to: 41-41


1096-1132: LGTM!

The test comprehensively verifies that the RESULT event handler correctly maps multiple JSON objects to ParseObject instances and emits them via the subscription. Test structure follows existing patterns.


1134-1136: LGTM!

Both tests appropriately verify that find() exists on the LiveQuerySubscription prototype and on subscription instances. The instance test also confirms the correct type.

Also applies to: 1138-1153

src/LiveQuerySubscription.ts (1)

95-95: LGTM!

The client field and constructor parameter additions are correctly implemented. The client reference is properly stored for use by the find() method.

Also applies to: 103-109

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 1, 2025
coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 1, 2025
coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 1, 2025
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 (Parse Server issue #9086)

2 participants