-
Notifications
You must be signed in to change notification settings - Fork 11.6k
fix: break circular dependency by passing creditCheckFn in messageDispatcher #25343
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…jection Break the 4-file circular dependency chain: credit-service → reminderScheduler → smsReminderManager → messageDispatcher → credit-service Solution: - Add optional creditCheckFn parameter to messageDispatcher functions - Thread creditCheckFn through the call chain: scheduleWorkflowReminders → scheduleSMSReminder/scheduleWhatsappReminder → messageDispatcher - When creditCheckFn is provided, use it; otherwise fall back to dynamic CreditService import for backward compatibility - This breaks the workflows → billing import while preserving immediate fallback behavior Changes: - messageDispatcher: Accept optional creditCheckFn parameter, use it if provided - smsReminderManager: Thread creditCheckFn through scheduleSMSReminder - whatsappReminderManager: Thread creditCheckFn through scheduleWhatsappReminder - reminderScheduler: Add creditCheckFn to ScheduleWorkflowRemindersArgs and pass through processWorkflowStep All type checks, lint checks, and unit tests pass. Co-Authored-By: [email protected] <[email protected]>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
…ency fix - Add creditCheckFn parameter to WorkflowService.scheduleFormWorkflows - Wire creditCheckFn from all 10 entry points that call workflow scheduling: * formSubmissionUtils.ts (form submissions) * roundRobinManualReassignment.ts (round-robin reassignment) * triggerFormSubmittedNoEventWorkflow.ts (form workflow trigger) * handleBookingRequested.ts (booking requests) * RegularBookingService.ts (2 calls - payment initiated & new bookings) * handleSeats.ts (seated bookings) * handleConfirmation.ts (2 calls - confirmation & payment) * handleMarkNoShow.ts (no-show updates) * confirm.handler.ts (booking rejection) - Update test expectations to use expect.objectContaining() - Fix pre-existing lint warning in handleMarkNoShow.ts (any type) - This completes the messageDispatcher circular dependency fix by ensuring creditCheckFn is actually passed through the call chain, breaking the 4-file circular dependency at runtime Co-Authored-By: [email protected] <[email protected]>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
… check error - Replace constrained type with generic type parameter - Add proper type guard for rejected promises - Fixes CI type check failure in handleMarkNoShow.ts:385 - Avoids 'any' type while accepting any fulfilled value shape Co-Authored-By: [email protected] <[email protected]>
E2E results are ready! |
2821381 to
4f4cf37
Compare
…backs - Wire creditCheckFn in packages/sms/sms-manager.ts (can safely import CreditService) - Create makeHandler factory pattern for CRON endpoints (scheduleSMSReminders.ts, scheduleWhatsappReminders.ts) - Wire creditCheckFn from apps/web CRON routes to factories - Add warning log in messageDispatcher when fallback is used - Complete creditCheckFn wiring from all direct callers (activateEventType.handler.ts, util.ts) This eliminates all fallbacks to dynamic import except as a safety net for unforeseen call sites. The circular dependency (workflows ↔ billing) remains acceptable as discussed with user (Option C). Co-Authored-By: [email protected] <[email protected]>
The scheduleFormWorkflows function now receives creditCheckFn as a parameter. Updated test assertions to use expect.objectContaining() with creditCheckFn: expect.any(Function) to account for the new dependency injection parameter. Co-Authored-By: [email protected] <[email protected]>
The sendSmsOrFallbackEmail function now receives creditCheckFn as a parameter. Updated test assertion to use expect.objectContaining() with creditCheckFn: expect.any(Function) to account for the new dependency injection parameter. Also removed teamId: undefined assertion as the key may be omitted entirely from the actual call. Co-Authored-By: [email protected] <[email protected]>
This commit completes the circular dependency fix by making creditCheckFn required throughout the call chain, eliminating the dynamic import fallback entirely. Changes: - Make creditCheckFn required in messageDispatcher functions (sendSmsOrFallbackEmail, scheduleSmsOrFallbackEmail) - Remove dynamic import fallback and warning log from messageDispatcher - Make creditCheckFn required in ScheduleTextReminderArgs (smsReminderManager) - Make creditCheckFn required in processWorkflowStep and ScheduleWorkflowRemindersArgs (reminderScheduler) - Add creditCheckFn to SendCancelledRemindersArgs and wire from handleCancelBooking The circular dependency is now fully broken - no more dynamic imports of CreditService from within the workflows package. All callers must explicitly provide creditCheckFn via dependency injection. Co-Authored-By: [email protected] <[email protected]>
…lows This commit fixes the CI type check error by making creditCheckFn required in WorkflowService.scheduleFormWorkflows. Previously, creditCheckFn was optional in scheduleFormWorkflows but required in scheduleWorkflowReminders, causing a type mismatch. Changes: - Make creditCheckFn required in scheduleFormWorkflows signature - Update WorkflowService.test.ts to pass mock creditCheckFn in all test cases - Add responseId and routedEventTypeId to test calls for completeness All callers of scheduleFormWorkflows already pass creditCheckFn, so this change is safe and completes the circular dependency fix. Co-Authored-By: [email protected] <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
13 issues found across 24 files
Prompt for AI agents (all 13 issues)
Understand the root cause of the following 13 issues and fix them.
<file name="packages/features/handleMarkNoShow.ts">
<violation number="1" location="packages/features/handleMarkNoShow.ts:307">
Bind CreditService.hasAvailableCredits before passing it as creditCheckFn; the current unbound method loses its this context and will throw at runtime, preventing reminders from being sent.</violation>
</file>
<file name="packages/features/ee/workflows/api/scheduleWhatsappReminders.ts">
<violation number="1" location="packages/features/ee/workflows/api/scheduleWhatsappReminders.ts:130">
Bind CreditService.hasAvailableCredits before passing it to scheduleSmsOrFallbackEmail; otherwise the callback runs with the wrong `this` and crashes when it calls private helpers.</violation>
</file>
<file name="packages/sms/sms-manager.ts">
<violation number="1" location="packages/sms/sms-manager.ts:51">
Passing `creditService.hasAvailableCredits` unbound drops its `this` context, so the credit check throws at runtime. Bind or wrap the method before injecting it.</violation>
</file>
<file name="packages/features/bookings/lib/handleSeats/handleSeats.ts">
<violation number="1" location="packages/features/bookings/lib/handleSeats/handleSeats.ts:135">
Bind the CreditService instance when wiring creditCheckFn; passing the method unbound causes runtime failures when messageDispatcher calls it without a `this` context.</violation>
</file>
<file name="packages/app-store/routing-forms/lib/formSubmissionUtils.ts">
<violation number="1" location="packages/app-store/routing-forms/lib/formSubmissionUtils.ts:236">
Passing the instance method without binding drops its `this` context, so any workflow reminder credit check will throw. Bind the method before passing it.</violation>
</file>
<file name="packages/features/bookings/lib/handleBookingRequested.ts">
<violation number="1" location="packages/features/bookings/lib/handleBookingRequested.ts:123">
Bind the CreditService instance when passing `creditCheckFn`; otherwise `this` becomes undefined and credit checks throw once the limit-reached path executes.</violation>
</file>
<file name="packages/features/ee/workflows/api/scheduleSMSReminders.ts">
<violation number="1" location="packages/features/ee/workflows/api/scheduleSMSReminders.ts:199">
creditCheckFn is passed an unbound instance method, so inside messageDispatcher `this` becomes undefined and credit checks throw before reminders can be scheduled. Bind the method to the CreditService instance.</violation>
</file>
<file name="packages/trpc/server/routers/viewer/workflows/activateEventType.handler.ts">
<violation number="1" location="packages/trpc/server/routers/viewer/workflows/activateEventType.handler.ts:425">
`creditService.hasAvailableCredits` is passed unbound, so `this` is undefined when the reminder invokes `creditCheckFn`, crashing credit checks.</violation>
</file>
<file name="packages/features/ee/round-robin/roundRobinManualReassignment.ts">
<violation number="1" location="packages/features/ee/round-robin/roundRobinManualReassignment.ts:618">
`creditCheckFn` is passed an unbound instance method, so `hasAvailableCredits` will throw when accessed without its `this` context.</violation>
</file>
<file name="packages/features/bookings/lib/handleCancelBooking.ts">
<violation number="1" location="packages/features/bookings/lib/handleCancelBooking.ts:377">
Bind CreditService.hasAvailableCredits before passing it as creditCheckFn; otherwise the callback throws because it relies on this.</violation>
</file>
<file name="packages/features/bookings/lib/handleConfirmation.ts">
<violation number="1" location="packages/features/bookings/lib/handleConfirmation.ts:374">
Passing `creditService.hasAvailableCredits` directly loses the `this` binding, so workflow reminders will crash when `creditCheckFn` runs. Bind the method (e.g., `.bind(creditService)` or wrap in a lambda) before passing it down.</violation>
</file>
<file name="packages/features/bookings/lib/service/RegularBookingService.ts">
<violation number="1" location="packages/features/bookings/lib/service/RegularBookingService.ts:2391">
Bind the hasAvailableCredits method before passing it into scheduleWorkflowsForNewBooking so the callback keeps the CreditService instance context.</violation>
</file>
<file name="packages/trpc/server/routers/viewer/workflows/util.ts">
<violation number="1" location="packages/trpc/server/routers/viewer/workflows/util.ts:847">
`creditService.hasAvailableCredits` is passed without binding, so the credit check throws when messageDispatcher calls it. Bind the method to the instance before injecting.</violation>
</file>
Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR
packages/features/ee/workflows/api/scheduleWhatsappReminders.ts
Outdated
Show resolved
Hide resolved
packages/features/ee/round-robin/roundRobinManualReassignment.ts
Outdated
Show resolved
Hide resolved
packages/features/bookings/lib/service/RegularBookingService.ts
Outdated
Show resolved
Hide resolved
| t: TFunction; | ||
| replyTo: string; | ||
| }; | ||
| creditCheckFn: CreditCheckFn; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
key change
| replyTo: string; | ||
| workflowStepId?: number; | ||
| }; | ||
| creditCheckFn: CreditCheckFn; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
key change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No issues found across 24 files
| const isRejected = <T>(x: PromiseSettledResult<T>): x is PromiseRejectedResult => x.status === "rejected"; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this used somewhere ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah no, will revert now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reverted
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No issues found across 24 files
What does this PR do?
This PR completes the circular dependency fix between the workflows and billing packages by making
creditCheckFna required parameter throughout the workflow reminder system, eliminating the dynamic import fallback entirely.Context: This builds on PR #25312 which fixed the
reminderSchedulercircular dependency. This PR addresses the remaining circular dependency inmessageDispatcherand related functions.The circular dependency:
The solution: Use dependency injection by making
creditCheckFnrequired and wiring it from all callers (which live outside the workflows package and can safely importCreditService).Mandatory Tasks