Skip to content

Conversation

@ThyMinimalDev
Copy link
Contributor

@ThyMinimalDev ThyMinimalDev commented Nov 5, 2025

What does this PR do?

Adds async email and SMS sending for booking events using Trigger.dev with a safe sync fallback to reduce request time and improve reliability. Integrates the tasker into RegularBookingService via DI, aligns logging with tslog, and loads Trigger.dev tasks dynamically to avoid test failures.

New Features
    Added Tasker abstraction with a primary Trigger.dev tasker (toggled by ENABLE_ASYNC_TASKER) and a sync fallback.
    Added Trigger.dev tasks and config within packages/features: request, confirm, reschedule, rr-reschedule, plus a simple logger.
    Hooked booking flow to dispatch tasks via BookingEmailAndSmsTasker; notifications are sent via BookingEmailSmsHandler.
    Introduced base Tasker utilities and DI modules to wire the tasker/handler into API services.
    Updated logger bridge to match tslog’s interface.
    Switched Trigger.dev task imports to dynamic to avoid loading the SDK during tests.
    Added team feature flag "booking-email-sms-tasker" to control rollout.
    Extended booking fetch to include attendee phone numbers and seat metadata for SMS.
    Added booking-notifications queue and retry policy; included trigger.config.ts and dev/deploy scripts.

Migration
    Set TRIGGER_SECRET_KEY and TRIGGER_API_URL; optionally set ENABLE_ASYNC_TASKER=true; run Trigger.dev via packages/features (yarn dev:trigger / yarn deploy:trigger).
    Optionally set LOGGER_BRIDGE_LOG_LEVEL to control API logging.
    Optionally enable the "booking-email-sms-tasker" feature flag.
    No changes needed if Trigger.dev isn’t configured—the sync fallback will handle notifications.

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • N/A I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. If N/A, write N/A here and check the checkbox.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

Summary by cubic

Adds async email and SMS sending for booking events using Trigger.dev with a safe sync fallback to reduce request time and improve reliability. Integrates the tasker into RegularBookingService via DI, aligns logging with tslog, and loads Trigger.dev tasks dynamically to avoid test failures.

  • New Features

    • Added Tasker abstraction with a primary Trigger.dev tasker (toggled by ENABLE_ASYNC_TASKER) and a sync fallback.
    • Added Trigger.dev tasks and config within packages/features: request, confirm, reschedule, rr-reschedule, plus a simple logger.
    • Hooked booking flow to dispatch tasks via BookingEmailAndSmsTasker; notifications are sent via BookingEmailSmsHandler.
    • Introduced base Tasker utilities and DI modules to wire the tasker/handler into API services.
    • Updated logger bridge to match tslog’s interface.
    • Switched Trigger.dev task imports to dynamic and moved heavy handler/workflow imports to runtime to reduce cold start and avoid test/circular import issues.
    • Added team feature flag "booking-email-sms-tasker" to control rollout.
    • Extended booking fetch to include attendee phone numbers and seat metadata for SMS.
    • Added booking-notifications queue and retry policy; included trigger.config.ts and dev/deploy scripts.
  • Migration

    • Set TRIGGER_SECRET_KEY and TRIGGER_API_URL; optionally set ENABLE_ASYNC_TASKER=true; run Trigger.dev via packages/features (yarn dev:trigger / yarn deploy:trigger).
    • Set TRIGGER_DEV_PROJECT_REF for Trigger.dev (used by packages/features/trigger.config.ts).
    • Optionally set LOGGER_BRIDGE_LOG_LEVEL to control API logging.
    • Optionally enable the "booking-email-sms-tasker" feature flag.
    • No changes needed if Trigger.dev isn’t configured—the sync fallback will handle notifications.

Written for commit 974fb49. Summary will update automatically on new commits.

@ThyMinimalDev ThyMinimalDev requested a review from a team November 5, 2025 12:18
@ThyMinimalDev ThyMinimalDev requested review from a team as code owners November 5, 2025 12:18
@keithwillcode keithwillcode added core area: core, team members only foundation platform Anything related to our platform plan labels Nov 5, 2025
@ThyMinimalDev ThyMinimalDev force-pushed the async-tasker-booking-email-and-sms branch from e9af47d to 4db7cd9 Compare November 5, 2025 12:19
@ThyMinimalDev ThyMinimalDev changed the title Async tasker booking email and sms feat: Booking Tasker Nov 5, 2025
@ThyMinimalDev ThyMinimalDev force-pushed the async-tasker-booking-email-and-sms branch from 4db7cd9 to dc59968 Compare November 5, 2025 15:29
@vercel
Copy link

vercel bot commented Nov 5, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
cal Ignored Ignored Nov 28, 2025 0:08am
cal-eu Ignored Ignored Nov 28, 2025 0:08am

Copy link
Contributor

@hbjORbj hbjORbj left a comment

Choose a reason for hiding this comment

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

Code looks great, tests and typechecks need to be fixed though. Will come back later for a 2nd review and some testing.

ThyMinimalDev and others added 4 commits November 7, 2025 10:26
…ests

The unit tests were failing because BookingEmailAndSmsTriggerTasker.ts had static imports of trigger files that depend on @trigger.dev/sdk. This caused Vitest to try to resolve the SDK at module load time, even though it should be optional.

Changed all imports in BookingEmailAndSmsTriggerTasker.ts from static to dynamic (using await import()) so the trigger files are only loaded when the tasker methods are actually called, not at module load time during tests.

This fixes the 'Failed to load url @trigger.dev/sdk' errors that were causing 28+ test failures.

Co-Authored-By: morgan@cal.com <morgan@cal.com>
@ThyMinimalDev ThyMinimalDev marked this pull request as ready for review November 27, 2025 08:58
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

8 issues found across 56 files

Prompt for AI agents (all 8 issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="packages/features/bookings/lib/tasker/BookingEmailAndSmsTasker.ts">

<violation number="1" location="packages/features/bookings/lib/tasker/BookingEmailAndSmsTasker.ts:33">
Early return bypasses try-catch error handling and logging. Unlike other actions, `rrReschedule` failures won&#39;t be logged and errors won&#39;t be caught. Consider assigning to `taskResponse` instead and letting the flow continue to the logging.</violation>
</file>

<file name="package.json">

<violation number="1" location="package.json:45">
Script naming inconsistency: should be `deploy:trigger` to match PR documentation and the underlying `@calcom/features` script name. Currently named `dev:deploy` which doesn&#39;t follow the `*:trigger` naming pattern.</violation>
</file>

<file name="packages/features/bookings/lib/tasker/BookingEmailAndSmsTaskService.ts">

<violation number="1" location="packages/features/bookings/lib/tasker/BookingEmailAndSmsTaskService.ts:137">
Hardcoding `changedOrganizer: true` and `isRescheduledByBooker: true` will cause incorrect email notifications. These values should reflect actual reschedule context - whether the organizer changed and who initiated the reschedule. Consider extending the payload type to include these fields or deriving them from booking data.</violation>
</file>

<file name="apps/api/v2/src/lib/logger.bridge.ts">

<violation number="1" location="apps/api/v2/src/lib/logger.bridge.ts:9">
Typo from search-and-replace: &quot;Add unknown other settings&quot; should be &quot;Add any other settings&quot;. The word &quot;any&quot; here was English (meaning &quot;additional&quot;), not the TypeScript type.</violation>
</file>

<file name="packages/lib/tasker/Tasker.ts">

<violation number="1" location="packages/lib/tasker/Tasker.ts:19">
Logical error in warning condition: uses `&amp;&amp;` instead of `||`. When only ONE env var is missing, the async tasker falls back to sync mode silently without logging a warning. This should use `||` to warn when EITHER env var is missing.</violation>
</file>

<file name="packages/features/package.json">

<violation number="1" location="packages/features/package.json:11">
Scripts use `npx trigger.dev@latest` which ignores the local devDependency and may cause version drift. Consider using `npx trigger.dev` (without `@latest`) to use the locally installed version for reproducible builds, or remove the devDependency if always using latest is intentional.</violation>
</file>

<file name="turbo.json">

<violation number="1" location="turbo.json:461">
The `dev:trigger` and `deploy:trigger` tasks are missing `cache: false`. Following the established pattern in this codebase (see `dev`, `deploy`, and `dx` tasks), development and deployment tasks should disable caching to ensure the command actually executes each time rather than returning cached results.</violation>
</file>

<file name="packages/features/bookings/repositories/BookingRepository.ts">

<violation number="1" location="packages/features/bookings/repositories/BookingRepository.ts:1315">
Using `steps: true` fetches all WorkflowStep fields including potentially sensitive data like `reminderBody`, `emailSubject`, `sendTo`, and `agentId`. Per project Prisma guidelines, explicitly select only the fields needed for the CalEvent builder instead of fetching the entire relation.</violation>
</file>

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

@ThyMinimalDev ThyMinimalDev marked this pull request as draft November 27, 2025 09:22
@ThyMinimalDev ThyMinimalDev marked this pull request as ready for review November 27, 2025 09:32
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

4 issues found across 56 files

Prompt for AI agents (all 4 issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="packages/features/bookings/di/BookingEmailSmsHandler.module.ts">

<violation number="1" location="packages/features/bookings/di/BookingEmailSmsHandler.module.ts:26">
Unused import and incorrect type export. `RegularBookingService` is imported but never used in the module&#39;s logic. Based on the pattern in other `.module.ts` files (e.g., `BookingCancelService.module.ts`, `RecurringBookingService.module.ts`), this should export the type of the class being bound (`BookingEmailSmsHandler`), not an unrelated service.</violation>
</file>

<file name="packages/features/bookings/di/tasker/BookingEmailAndSmsTriggerDevTasker.container.ts">

<violation number="1" location="packages/features/bookings/di/tasker/BookingEmailAndSmsTriggerDevTasker.container.ts:8">
Function name mismatch: `getBookingEmailAndSmsSyncTasker` should be `getBookingEmailAndSmsTriggerDevTasker` to match the return type and differentiate from the actual Sync tasker container. This appears to be a copy-paste error that will cause confusion and potential naming collisions when both containers are imported.</violation>
</file>

<file name="packages/lib/tasker/Tasker.ts">

<violation number="1" location="packages/lib/tasker/Tasker.ts:2">
Static import of `@trigger.dev/sdk` will load the SDK even when async tasking is disabled. Consider using dynamic import to avoid loading the SDK during tests or when `ENABLE_ASYNC_TASKER` is false, consistent with the PR&#39;s stated approach for other Trigger.dev imports.</violation>

<violation number="2" location="packages/lib/tasker/Tasker.ts:41">
Rule violated: **Avoid Logging Sensitive Information**

Logging `{ args }` will expose PII (emails, phone numbers, booking details) in logs. Since this is a booking email/SMS tasker, the args will contain attendee contact information. Consider removing `args` from the log statement or redacting sensitive fields before logging.</violation>
</file>

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

@@ -0,0 +1,79 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { configure } from "@trigger.dev/sdk";
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 27, 2025

Choose a reason for hiding this comment

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

Static import of @trigger.dev/sdk will load the SDK even when async tasking is disabled. Consider using dynamic import to avoid loading the SDK during tests or when ENABLE_ASYNC_TASKER is false, consistent with the PR's stated approach for other Trigger.dev imports.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/lib/tasker/Tasker.ts, line 2:

<comment>Static import of `@trigger.dev/sdk` will load the SDK even when async tasking is disabled. Consider using dynamic import to avoid loading the SDK during tests or when `ENABLE_ASYNC_TASKER` is false, consistent with the PR&#39;s stated approach for other Trigger.dev imports.</comment>

<file context>
@@ -0,0 +1,79 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import { configure } from &quot;@trigger.dev/sdk&quot;;
+
+import { ENABLE_ASYNC_TASKER } from &quot;../constants&quot;;
</file context>
Fix with Cubic

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file (reviewed changes from recent commits).

Prompt for AI agents (all 1 issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="packages/platform/atoms/vite.config.ts">

<violation number="1" location="packages/platform/atoms/vite.config.ts:73">
Standalone comma creates an empty array slot in the externals array. This is likely unintentional and should be removed.</violation>
</file>

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

"@prisma/client",
"react/jsx-dev-runtime",
, "react-awesome-query-builder", "react-awesome-query-builder", "react-awesome-query-builder"],
,
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 28, 2025

Choose a reason for hiding this comment

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

Standalone comma creates an empty array slot in the externals array. This is likely unintentional and should be removed.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/platform/atoms/vite.config.ts, line 73:

<comment>Standalone comma creates an empty array slot in the externals array. This is likely unintentional and should be removed.</comment>

<file context>
@@ -71,7 +70,12 @@ export default defineConfig(({ mode }) =&gt; {
           &quot;@prisma/client&quot;,
           &quot;react/jsx-dev-runtime&quot;,
-        , &quot;react-awesome-query-builder&quot;, &quot;react-awesome-query-builder&quot;, &quot;react-awesome-query-builder&quot;],
+          ,
+          &quot;react-awesome-query-builder&quot;,
+          &quot;react-awesome-query-builder&quot;,
</file context>
Fix with Cubic

Copy link
Contributor

@emrysal emrysal left a comment

Choose a reason for hiding this comment

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

LGTM! 🚀 🥳

@ThyMinimalDev ThyMinimalDev merged commit a050ccb into main Nov 28, 2025
77 of 88 checks passed
@ThyMinimalDev ThyMinimalDev deleted the async-tasker-booking-email-and-sms branch November 28, 2025 14:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core area: core, team members only ❗️ .env changes contains changes to env variables foundation platform Anything related to our platform plan ready-for-e2e size/XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants