Skip to content

SMS workflow reminder retry count tracking#7

Draft
ShashankFC wants to merge 1 commit into
sms-retry-basefrom
sms-retry-enhanced
Draft

SMS workflow reminder retry count tracking#7
ShashankFC wants to merge 1 commit into
sms-retry-basefrom
sms-retry-enhanced

Conversation

@ShashankFC

@ShashankFC ShashankFC commented Dec 31, 2025

Copy link
Copy Markdown
Collaborator

Test 9nn

Summary by CodeRabbit

  • New Features

    • Implemented automatic retry capability for SMS reminders to handle delivery failures.
  • Bug Fixes

    • Improved error handling for failed SMS reminder deliveries with enhanced tracking and retry mechanisms.

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

nn---n*Replicated from [ai-code-review-evaluation/cal.com-coderabbit#9](https://github.com/ai-code-review-evaluation/cal.com-coderabbit/pull/9)*

* add retry count to workflow reminder

* add logic to for retry count

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
@ShashankFC

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jan 8, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jan 8, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This change introduces retry tracking for SMS reminders by adding a retryCount field to the WorkflowReminder model. The database schema and migration are updated to persist this field, and the SMS scheduling logic is enhanced to increment the retry count when scheduling fails or encounters errors. Cleanup logic filters based on method, date, and retry count thresholds.

Changes

Cohort / File(s) Summary
Database Schema & Migration
packages/prisma/schema.prisma, packages/prisma/migrations/20240508134359_add_retry_count_to_workflow_reminder/migration.sql
Added retryCount integer field with default value 0 to WorkflowReminder model. Includes SQL migration for schema alteration.
SMS Scheduling Logic
packages/features/ee/workflows/api/scheduleSMSReminders.ts
Extended unscheduled reminder queries to include retryCount. Modified cleanup filter to use OR condition for method/date or retry threshold. Increment retryCount on scheduling failures and caught errors.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A retry count hops into view,
For SMS reminders tried anew,
When schedules fail, we retry with care,
Resilience blooms everywhere! 🌸

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'SMS workflow reminder retry count tracking' directly and specifically summarizes the main change: adding retry count tracking to SMS workflow reminders.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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

@ShashankFC

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jan 8, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @packages/features/ee/workflows/api/scheduleSMSReminders.ts:
- Around line 29-45: The deletion predicate is too broad:
prisma.workflowReminder.deleteMany currently uses OR with one clause checking
method: WorkflowMethods.SMS and scheduledDate lte, and another clause checking
retryCount gt 1 which matches reminders of any method; narrow the second clause
to only apply to SMS reminders by making both OR branches include method:
WorkflowMethods.SMS (i.e., change the OR array to [{ method:
WorkflowMethods.SMS, scheduledDate: { lte: ... } }, { method:
WorkflowMethods.SMS, retryCount: { gt: 1 } }]) so only SMS reminders are deleted
for either being past scheduledDate or exceeding retryCount.
🧹 Nitpick comments (2)
packages/features/ee/workflows/api/scheduleSMSReminders.ts (2)

178-187: Consider adding explicit retry limit checks and error tracking.

While incrementing retryCount on scheduling failure is correct, several improvements would make the retry logic more robust:

  1. Missing retry limit check before scheduling: The code attempts to schedule without checking if retryCount has already reached the limit. Consider checking reminder.retryCount >= MAX_RETRIES before attempting to schedule.

  2. No failure reason captured: When scheduledSMS is falsy, the reason for failure is lost. Consider logging or persisting error details for debugging.

  3. Undocumented retry threshold: The deletion logic uses retryCount > 1 (deletes at 2+), meaning reminders get 2 total attempts. This should be documented as a constant (e.g., MAX_RETRY_COUNT = 1).

📋 Suggested improvements

Add a constant at the top of the file:

const MAX_RETRY_COUNT = 1; // Allow 2 total attempts (0 and 1)

Then check before scheduling:

for (const reminder of unscheduledReminders) {
  // Skip if already exceeded retry limit
  if (reminder.retryCount > MAX_RETRY_COUNT) {
    continue;
  }
  
  // ... existing code ...
}

And update the deletion condition to use the same constant:

  retryCount: {
-   gt: 1,
+   gt: MAX_RETRY_COUNT,
  },

189-199: Improve error handling and consider structured error logging.

The catch block correctly increments retryCount, but the error handling could be more robust:

  1. Console logging limitations: Line 198 logs to console, which may not be retained in production environments and lacks structure for monitoring/alerting.

  2. Same retry limit concerns: As with the scheduling failure case (lines 178-187), there's no pre-check for retry limits before attempting to schedule.

  3. Silent failure potential: If the prisma.workflowReminder.update itself throws an error, the outer catch doesn't handle it, potentially causing the entire cron job to fail.

📋 Suggested improvements

Consider structured error logging and defensive error handling:

  } catch (error) {
+   console.error(`Error scheduling SMS for reminder ${reminder.id}:`, {
+     reminderId: reminder.id,
+     bookingUid: reminder.booking?.uid,
+     error: error instanceof Error ? error.message : String(error),
+     retryCount: reminder.retryCount,
+   });
+   
+   try {
      await prisma.workflowReminder.update({
        where: {
          id: reminder.id,
        },
        data: {
          retryCount: reminder.retryCount + 1,
        },
      });
+   } catch (updateError) {
+     console.error(`Failed to update retry count for reminder ${reminder.id}:`, updateError);
+   }
-   console.log(`Error scheduling SMS with error ${error}`);
  }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 917c7b0 and 2dae0bf.

📒 Files selected for processing (3)
  • packages/features/ee/workflows/api/scheduleSMSReminders.ts
  • packages/prisma/migrations/20240508134359_add_retry_count_to_workflow_reminder/migration.sql
  • packages/prisma/schema.prisma
🧰 Additional context used
🧬 Code graph analysis (1)
packages/features/ee/workflows/api/scheduleSMSReminders.ts (1)
packages/features/ee/workflows/lib/getWorkflowReminders.ts (2)
  • select (112-172)
  • PartialWorkflowReminder (35-40)
🔇 Additional comments (3)
packages/prisma/schema.prisma (1)

1000-1000: LGTM! Clean addition of retry tracking field.

The retryCount field is properly typed as Int with a sensible default of 0, which correctly initializes the retry counter for new and existing workflow reminders.

packages/prisma/migrations/20240508134359_add_retry_count_to_workflow_reminder/migration.sql (1)

1-2: LGTM! Migration aligns with schema changes.

The migration correctly adds the retryCount column with NOT NULL DEFAULT 0, which safely handles existing rows in the WorkflowReminder table.

packages/features/ee/workflows/api/scheduleSMSReminders.ts (1)

48-60: LGTM! Properly extends query to include retry tracking.

The select object correctly includes retryCount, and the type assertion (PartialWorkflowReminder & { retryCount: number })[] accurately reflects the extended result structure.

Comment on lines 29 to 45
await prisma.workflowReminder.deleteMany({
where: {
method: WorkflowMethods.SMS,
scheduledDate: {
lte: dayjs().toISOString(),
},
OR: [
{
method: WorkflowMethods.SMS,
scheduledDate: {
lte: dayjs().toISOString(),
},
},
{
retryCount: {
gt: 1,
},
},
],
},
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Overly broad deletion condition risks unintended data loss.

The OR logic at Line 31 will delete any WorkflowReminder with retryCount > 1, regardless of method (SMS, EMAIL, WHATSAPP) or scheduled date. This can delete non-SMS reminders or reminders that are still pending processing.

The intent appears to be: delete SMS reminders that are either past their scheduled date OR have exceeded retry limits. The second condition should be scoped to SMS reminders.

🔧 Proposed fix
  await prisma.workflowReminder.deleteMany({
    where: {
-     OR: [
-       {
-         method: WorkflowMethods.SMS,
-         scheduledDate: {
-           lte: dayjs().toISOString(),
-         },
-       },
-       {
-         retryCount: {
-           gt: 1,
-         },
-       },
-     ],
+     method: WorkflowMethods.SMS,
+     OR: [
+       {
+         scheduledDate: {
+           lte: dayjs().toISOString(),
+         },
+       },
+       {
+         retryCount: {
+           gt: 1,
+         },
+       },
+     ],
    },
  });
🤖 Prompt for AI Agents
In @packages/features/ee/workflows/api/scheduleSMSReminders.ts around lines 29 -
45, The deletion predicate is too broad: prisma.workflowReminder.deleteMany
currently uses OR with one clause checking method: WorkflowMethods.SMS and
scheduledDate lte, and another clause checking retryCount gt 1 which matches
reminders of any method; narrow the second clause to only apply to SMS reminders
by making both OR branches include method: WorkflowMethods.SMS (i.e., change the
OR array to [{ method: WorkflowMethods.SMS, scheduledDate: { lte: ... } }, {
method: WorkflowMethods.SMS, retryCount: { gt: 1 } }]) so only SMS reminders are
deleted for either being past scheduledDate or exceeding retryCount.

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.

2 participants