Skip to content

Conversation

@hmshuv
Copy link

@hmshuv hmshuv commented Dec 25, 2025

Description

This PR refactors upcomingRoom-isTime-checker and upcomingRoom-Message-Notification to improve code quality, robustness, and readability.

Changes Made

upcomingRoom-isTime-checker

  • Replaced manual string splitting for dates with standard new Date() parsing
  • Removed excessive debug logs (log("here"), etc.)
  • Updated var to const/let
  • Wrapped logic in a try-catch block for better error handling

upcomingRoom-Message-Notification

  • Removed debug logs
  • Added safety checks to ensure arrays exist before spreading
  • Implemented token deduplication to prevent sending duplicate notifications to the same user

Related Issue

Fixes #130

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have verified the changes locally (via manual review/testing)

Note: Ready for review! Happy to address any feedback or make additional improvements.

Summary by CodeRabbit

  • Refactor

    • Improved notification delivery: token deduplication, consolidated send flow with multicast messaging, centralized error handling, and clearer success/error feedback.
    • Streamlined room-timing checks: robust date parsing, simplified time calculations, and more reliable activation logic.
  • Chores

    • Updated function interfaces and standardized logging for consistency and maintainability.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 25, 2025

Warning

Rate limit exceeded

@hmshuv has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 5 minutes and 8 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 2b72719 and d006fc3.

📒 Files selected for processing (1)
  • functions/upcomingRoom-Message-Notification/src/main.js
📝 Walkthrough

Walkthrough

Two cloud functions were refactored: upcomingRoom-Message-Notification now consolidates token collection, deduplicates tokens, and sends multicast notifications with improved error handling; upcomingRoom-isTime-checker now uses Date parsing, centralized try/catch error handling, and an updated function signature that accepts an error callback.

Changes

Cohort / File(s) Summary
Message Notification Refactor
functions/upcomingRoom-Message-Notification/src/main.js
Consolidated async token collection from subscriber documents and room creator, validated and deduplicated tokens, built platform-specific multicast payload, and sent via getMessaging(app).sendEachForMulticast; added try/catch, concise contextual logs, early return when no tokens, and 500 JSON error responses.
isTime Checker Refactor
functions/upcomingRoom-isTime-checker/src/main.js
Signature updated to accept error callback; replaced manual string-splitting with Date parsing and simpler time calculations; wrapped processing in try/catch with centralized error handling and JSON success/error responses; modernized const/let usage and removed verbose debug logs.

Sequence Diagram(s)

sequenceDiagram
  participant Scheduler as Cron
  participant Checker as isTime-checker
  participant DB as Appwrite DB
  participant Notifier as Message-Notification
  participant FCM as Firebase Messaging

  Scheduler->>Checker: Trigger function
  Checker->>DB: List upcomingRoom documents
  DB-->>Checker: upcomingRoom list
  Checker->>DB: Update room.isTime when within window
  Checker-->>Scheduler: Success response

  Note over Notifier,DB: Notification flow (separate trigger)
  Notifier->>DB: Query subscribers for room
  DB-->>Notifier: Subscriber docs (with tokens)
  Notifier->>Notifier: Aggregate & deduplicate tokens
  Notifier->>FCM: sendEachForMulticast(multicastMessage)
  FCM-->>Notifier: Responses per token
  Notifier-->>Caller: Completion JSON
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

gsoc

Poem

🐰 Hop-hop, I checked the time and squeaked,
Dates parsed cleanly, logs no longer leaked,
Tokens gathered, duplicates sent away,
Multicast hops off and saves the day —
A rabbit twitches nose for refactor play! 🎉

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: refactoring two cloud functions for improved robustness through better date parsing, logging, and error handling.
Linked Issues check ✅ Passed The PR successfully addresses all coding objectives from issue #130: robust date parsing with new Date() [#130], removal of debug logs [#130], const/let modernization [#130], safety checks for arrays [#130], and token deduplication [#130].
Out of Scope Changes check ✅ Passed All changes directly align with issue #130 objectives; no out-of-scope modifications detected beyond the intended refactoring scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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.

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: 4

🧹 Nitpick comments (2)
functions/upcomingRoom-isTime-checker/src/main.js (2)

37-37: Add safety check for the isTime field.

The code assumes document["isTime"] exists and is a boolean, but doesn't validate this. If the field is missing or has an unexpected type, the comparison could behave unexpectedly.

🔎 Proposed fix with safety check
-if (timeLeftInMinutes <= 5 && timeLeftInMinutes >= -5 && document["isTime"] === false) {
+if (timeLeftInMinutes <= 5 && timeLeftInMinutes >= -5 && document["isTime"] !== true) {

This change treats missing or falsy isTime values the same as false, making the code more defensive.


50-56: Consider removing commented notification logic.

The commented notification code is legacy and not executed. If this logic is no longer needed (as suggested by the PR objectives to clean up the codebase), consider removing it entirely rather than keeping it as commented code. If it's kept for reference, add a comment explaining why.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 795f29b and fd9cec3.

📒 Files selected for processing (2)
  • functions/upcomingRoom-Message-Notification/src/main.js
  • functions/upcomingRoom-isTime-checker/src/main.js
🧰 Additional context used
🧬 Code graph analysis (2)
functions/upcomingRoom-Message-Notification/src/main.js (1)
functions/upcomingRoom-isTime-checker/src/main.js (4)
  • admin (2-2)
  • client (11-11)
  • sdk (1-1)
  • database (12-12)
functions/upcomingRoom-isTime-checker/src/main.js (1)
functions/upcomingRoom-Message-Notification/src/main.js (3)
  • client (12-12)
  • sdk (1-1)
  • database (13-13)
🔇 Additional comments (9)
functions/upcomingRoom-isTime-checker/src/main.js (5)

10-18: LGTM! Good addition of error callback.

The function signature now includes the error callback, which enables structured error handling. The Appwrite client setup follows best practices with environment variable configuration.


20-24: LGTM! Proper error handling structure.

The addition of try-catch wrapping the main logic aligns with the PR objectives for improved robustness and error handling.


59-61: LGTM! Clean success response.

The success response is clear and appropriate for the function's purpose.


63-69: LGTM! Solid error handling.

The error handling properly uses the error callback for logging and returns an appropriate 500 status with error details. This aligns well with the PR objectives for improved error handling.


37-37: Clarify the intentional scope of late room activation in the design.

The condition timeLeftInMinutes >= -5 is documented in the code comment as intentional ("Check if time is within +/- 5 minutes"), allowing rooms to activate up to 5 minutes past their scheduled start time. Since this cron function runs every 5 minutes, rooms may not be processed until 5 minutes after their scheduled time, making this threshold catch late-arriving checks.

However, the README documentation does not explicitly mention support for late activation (it only states "less than or equal to 5 minutes"). Confirm whether this behavior aligns with product requirements:

  • Is activating rooms 5 minutes past their scheduled time the intended behavior?
  • If so, update the README to document the -5 minute grace period.
functions/upcomingRoom-Message-Notification/src/main.js (4)

33-47: Good implementation of array safety checks.

The safety checks using Array.isArray() before spreading tokens correctly address the issue objectives. This prevents runtime errors when registrationTokens or creator_fcm_tokens are undefined or not arrays.


49-50: Token deduplication is correctly implemented.

Using Set for deduplication is efficient and idiomatic. This addresses the PR objective to avoid sending duplicate notifications.


22-82: Overall structure improvements look good.

The refactoring successfully achieves the PR objectives:

  • Try-catch error handling is properly implemented
  • Excessive debug logs are removed in favor of concise, contextual logging
  • var is replaced with const
  • Safety checks and deduplication are correctly added

76-82: The res.json() method in Appwrite Functions correctly supports the two-argument signature res.json(data, statusCode). The 500 status code at line 81 will be set correctly. This pattern is documented in the official Appwrite Functions API and is used consistently throughout this codebase.

Likely an incorrect or invalid review comment.

priority: "high"

try {
const { roomId, payload } = JSON.parse(req.body);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Handle cases where req.body may already be parsed or undefined.

In Appwrite Functions, req.body can be a pre-parsed object (depending on content-type headers) or undefined. Calling JSON.parse() on an object throws "Unexpected token o in JSON", which is confusing.

🔎 Proposed fix
-    const { roomId, payload } = JSON.parse(req.body);
+    const body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body;
+    const { roomId, payload } = body;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { roomId, payload } = JSON.parse(req.body);
const body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body;
const { roomId, payload } = body;
🤖 Prompt for AI Agents
In functions/upcomingRoom-Message-Notification/src/main.js around line 23, avoid
blindly calling JSON.parse on req.body; instead check if req.body is undefined,
a string, or already an object. If undefined, set a safe default (e.g., {} or
return a 400); if typeof req.body === "string" parse it inside a try/catch and
handle parse errors (log and return an error response); if typeof req.body ===
"object" use it directly; finally validate that roomId and payload exist before
proceeding.

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)
functions/upcomingRoom-Message-Notification/src/main.js (1)

54-65: Message structure correctly addresses past feedback.

The multicast message structure now:

  • Removes the invalid top-level priority field
  • Correctly sets android.priority for Android devices
  • Adds apns headers with apns-priority: "10" for iOS high-priority delivery

This properly addresses the previous review comment.

Optional enhancement: Validate payload structure

Consider validating that payload contains expected notification fields (e.g., title, body) before building the message. This would provide clearer error messages if the payload is malformed:

if (!payload.title || !payload.body) {
  throw new Error('Payload must contain title and body fields');
}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd9cec3 and 796b12d.

📒 Files selected for processing (2)
  • functions/upcomingRoom-Message-Notification/src/main.js
  • functions/upcomingRoom-isTime-checker/src/main.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • functions/upcomingRoom-isTime-checker/src/main.js
🧰 Additional context used
🧬 Code graph analysis (1)
functions/upcomingRoom-Message-Notification/src/main.js (1)
functions/upcomingRoom-isTime-checker/src/main.js (3)
  • client (11-11)
  • sdk (1-1)
  • database (12-12)
🔇 Additional comments (5)
functions/upcomingRoom-Message-Notification/src/main.js (5)

1-8: LGTM: Firebase Admin initialization is correct.

The module-level initialization with service account credentials follows best practices. If the service account file is missing or invalid, the function will fail fast at load time, which is appropriate for cloud function deployments.


34-38: Excellent safety checks for array operations.

The code properly validates that registrationTokens exists and is an array before spreading, preventing potential runtime errors. This successfully addresses the PR objective for adding array safety checks.


40-48: Consistent safety checks applied.

The same defensive pattern is correctly applied when collecting creator tokens, ensuring creator_fcm_tokens exists and is an array before spreading. This consistency improves maintainability.


50-51: Token deduplication implemented correctly.

Using a Set for deduplication is clean and efficient. This successfully addresses the PR objective to prevent duplicate notifications.


82-86: No issues found. The res.json(payload, statusCode) syntax used in the error handler is the correct Appwrite Functions API for returning JSON responses with status codes.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
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: 0

🧹 Nitpick comments (5)
functions/upcomingRoom-Message-Notification/src/main.js (5)

11-11: Consider using let instead of const for semantically mutable arrays.

While const is technically correct (prevents reassignment but allows mutation), using let for subscribersTokens would more clearly signal that the array contents will change throughout the function.

🔎 Optional refactor
-  const subscribersTokens = [];
+  let subscribersTokens = [];

26-30: Consider validating the structure of payload and type of roomId.

The current validation ensures roomId and payload are present, but doesn't verify their structure or types. For Firebase Cloud Messaging, payload should typically contain title and body fields, and roomId should be a non-empty string.

🔎 Proposed validation enhancement
     if (!roomId || !payload) {
       return res.json({
         message: 'Missing required fields',
         error: 'roomId and payload are required'
       }, 400);
     }
+
+    if (typeof roomId !== 'string' || roomId.trim() === '') {
+      return res.json({
+        message: 'Invalid roomId',
+        error: 'roomId must be a non-empty string'
+      }, 400);
+    }
+
+    if (!payload.title || !payload.body) {
+      return res.json({
+        message: 'Invalid payload',
+        error: 'payload must contain title and body fields'
+      }, 400);
+    }

41-45: Good array safety check implementation!

The Array.isArray() check before spreading tokens correctly addresses the PR objective. However, consider validating that individual tokens are non-empty strings to prevent invalid tokens from reaching Firebase Cloud Messaging.

🔎 Optional enhancement to filter invalid tokens
     subscriberList.documents.forEach(subscriber => {
       if (subscriber["registrationTokens"] && Array.isArray(subscriber["registrationTokens"])) {
-        subscribersTokens.push(...subscriber["registrationTokens"]);
+        const validTokens = subscriber["registrationTokens"].filter(
+          token => typeof token === 'string' && token.trim() !== ''
+        );
+        subscribersTokens.push(...validTokens);
       }
     });

53-55: Array safety check correctly implemented.

The guard condition mirrors the subscriber token collection pattern. As with subscriber tokens, consider filtering invalid tokens here as well.

🔎 Optional enhancement
     if (roomDocument["creator_fcm_tokens"] && Array.isArray(roomDocument["creator_fcm_tokens"])) {
-      subscribersTokens.push(...roomDocument["creator_fcm_tokens"]);
+      const validTokens = roomDocument["creator_fcm_tokens"].filter(
+        token => typeof token === 'string' && token.trim() !== ''
+      );
+      subscribersTokens.push(...validTokens);
     }

60-82: Multicast notification implementation looks solid.

The message structure with Android and APNs high-priority configuration is correct, and sendEachForMulticast is the appropriate method for sending to multiple tokens. The past review comment regarding the invalid top-level priority field has been properly addressed.

Consider logging which specific tokens failed for easier debugging in production environments.

🔎 Optional enhancement for detailed failure logging
       const response = await getMessaging(app).sendEachForMulticast(message);
       if (response.failureCount > 0) {
-        log(`Failed to send ${response.failureCount} notifications`);
+        const failedTokens = response.responses
+          .map((r, idx) => r.success ? null : uniqueTokens[idx])
+          .filter(t => t !== null);
+        log(`Failed to send ${response.failureCount} notifications to tokens: ${failedTokens.join(', ')}`);
       } else {
         log('Notifications were sent successfully');
       }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 796b12d and 2b72719.

📒 Files selected for processing (1)
  • functions/upcomingRoom-Message-Notification/src/main.js
🧰 Additional context used
🧬 Code graph analysis (1)
functions/upcomingRoom-Message-Notification/src/main.js (1)
functions/upcomingRoom-isTime-checker/src/main.js (3)
  • client (11-11)
  • sdk (1-1)
  • database (12-12)
🔇 Additional comments (2)
functions/upcomingRoom-Message-Notification/src/main.js (2)

57-58: Excellent token deduplication implementation!

Using Set to deduplicate tokens is clean, efficient, and directly addresses the PR objective to prevent duplicate notifications.


88-94: Robust error handling implementation!

The try-catch block with structured error logging and a clear 500 response effectively addresses the PR objective to improve error handling and robustness.

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.

Refactor upcomingRoom-isTime-checker and upcomingRoom-Message-Notification functions

1 participant