Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 2 Skipped Deployments
|
WalkthroughThe changes introduce improved campaign cancellation and subscriber targeting logic. Campaigns can now be cancelled in additional states, and cancellation atomically updates all pending messages to a new "CANCELLED" status. Subscriber selection for campaigns is now strictly filtered by associated lists. Release notes and UI elements have been updated accordingly. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant WebApp
participant Backend
participant DB
User->>WebApp: Click "Cancel" on campaign (CREATING/SENDING/SCHEDULED)
WebApp->>Backend: cancelCampaign(campaignId)
Backend->>DB: Begin transaction
Backend->>DB: Update campaign status to CANCELLED
Backend->>DB: Update all related messages (QUEUED/PENDING/RETRYING) to CANCELLED
DB-->>Backend: Transaction committed
Backend-->>WebApp: Success response
WebApp-->>User: UI updates to show cancellation
sequenceDiagram
participant CronJob
participant DB
CronJob->>DB: Get campaigns with status QUEUED
CronJob->>DB: For each campaign, get associated list IDs
CronJob->>DB: Fetch subscribers filtered by selected list IDs
DB-->>CronJob: Return filtered subscribers
CronJob->>DB: Create messages only for filtered subscribers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
apps/backend/src/index.ts (1)
13-34: Good migration logic, but consider adding error handling.The migration logic correctly ensures backwards compatibility by updating message statuses for already cancelled campaigns. The approach is sound and idempotent.
Consider adding error handling for the database connection and migration:
-prisma.$connect().then(async () => { +prisma.$connect().then(async () => { console.log("Connected to database") // For backwards compatibility, set all messages that have campaign status === "CANCELLED" to "CANCELLED" - await prisma.message.updateMany({ + try { + await prisma.message.updateMany({ where: { Campaign: { status: "CANCELLED", }, status: { in: ["QUEUED", "PENDING", "RETRYING"], }, }, data: { status: "CANCELLED", }, - }) + }) + console.log("Migration completed successfully") + } catch (error) { + console.error("Migration failed:", error) + process.exit(1) + } app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`) }) +}).catch((error) => { + console.error("Failed to connect to database:", error) + process.exit(1) })apps/backend/src/cron/processQueuedCampaigns.ts (1)
122-132: Consider optimizing the database query structure.While the logic is correct, fetching campaign lists in a separate query could be optimized by including the
CampaignListsrelation in the main campaign query earlier in the function.Consider this optimization to reduce database calls:
const queuedCampaigns = await prisma.campaign.findMany({ where: { status: "CREATING", }, include: { + CampaignLists: { + select: { listId: true }, + }, Organization: { include: { GeneralSettings: true, SmtpSettings: true, }, }, Template: true, }, })Then replace lines 122-132 with:
- const campaignLists = await prisma.campaign.findUnique({ - where: { id: campaign.id }, - select: { - CampaignLists: { - select: { listId: true }, - }, - }, - }) - - const selectedListIds = - campaignLists?.CampaignLists.map((cl) => cl.listId) || [] + const selectedListIds = campaign.CampaignLists.map((cl) => cl.listId)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
RELEASE_NOTES.md(1 hunks)apps/backend/prisma/schema.prisma(1 hunks)apps/backend/src/campaign/mutation.ts(3 hunks)apps/backend/src/campaign/router.ts(2 hunks)apps/backend/src/cron/processQueuedCampaigns.ts(3 hunks)apps/backend/src/cron/sendMessages.ts(3 hunks)apps/backend/src/index.ts(1 hunks)apps/web/src/pages/dashboard/campaigns/[id]/campaign-actions.tsx(1 hunks)package.json(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (5)
apps/backend/src/campaign/router.ts (1)
apps/backend/src/campaign/mutation.ts (1)
cancelCampaign(391-443)
apps/backend/src/index.ts (2)
apps/backend/src/utils/prisma.ts (1)
prisma(3-28)apps/backend/src/app.ts (1)
app(38-38)
apps/backend/src/cron/sendMessages.ts (1)
apps/backend/src/utils/prisma.ts (1)
prisma(3-28)
apps/backend/src/campaign/mutation.ts (1)
apps/backend/src/utils/prisma.ts (1)
prisma(3-28)
apps/backend/src/cron/processQueuedCampaigns.ts (1)
apps/backend/src/utils/prisma.ts (1)
prisma(3-28)
🪛 LanguageTool
RELEASE_NOTES.md
[uncategorized] ~7-~7: You might be missing the article “the” here.
Context: ...es - Fixed campaign creation targeting wrong subscribers (now filters by selected li...
(AI_EN_LECTOR_MISSING_DETERMINER_THE)
🔇 Additional comments (17)
apps/backend/prisma/schema.prisma (1)
201-201: LGTM! Enum extension correctly implements cancellation status.The addition of
CANCELLEDto theMessageStatusenum properly supports the new campaign cancellation workflow. This change is backwards compatible and aligns with the transaction logic that updates both campaign and message statuses atomically.package.json (1)
2-2: Appropriate version bump for bug fix release.The patch version increment from "0.9.0" to "0.9.1" correctly follows semantic versioning for this bug fix release.
apps/backend/src/campaign/router.ts (1)
7-7: LGTM! Naming consistency fix aligns router with implementation.The import and router mapping changes correctly align with the actual
cancelCampaignfunction name shown in the mutation implementation. This ensures consistent naming throughout the codebase.Also applies to: 20-20
apps/web/src/pages/dashboard/campaigns/[id]/campaign-actions.tsx (1)
203-205: LGTM! UI correctly extends cancellation to additional campaign states.The addition of
"CREATING"and"SCHEDULED"cases properly extends the cancel button functionality to match the backend capabilities. The fall-through behavior efficiently reuses the existing cancel button implementation, and this aligns with the backend mutation logic that supports cancelling campaigns in these states.RELEASE_NOTES.md (1)
3-8: LGTM! Clear and informative release notes.The release notes effectively document the new features and bug fixes. The static analysis hint about the missing "the" article is a false positive - the current phrasing is grammatically correct and appropriate for technical documentation.
🧰 Tools
🪛 LanguageTool
[uncategorized] ~7-~7: You might be missing the article “the” here.
Context: ...es - Fixed campaign creation targeting wrong subscribers (now filters by selected li...(AI_EN_LECTOR_MISSING_DETERMINER_THE)
apps/backend/src/cron/sendMessages.ts (3)
53-70: LGTM! Excellent implementation of message status independence.The decoupling of message status from campaign status is well-implemented:
- Clear comments explain the rationale
- Proper organization filtering ensures security
- Logic correctly allows retrying individual messages regardless of campaign state
This change enables the feature mentioned in the release notes where individual messages can be retried independently.
89-92: Good addition of organization filter for consistency.Adding the organization filter to the retrying messages count query maintains consistency with the main message filtering logic and ensures proper security isolation.
103-103: Correct inclusion of CANCELLED status in completion logic.Adding "CANCELLED" to the list of statuses that mark a campaign as completed is necessary for proper campaign lifecycle management with the new cancellation behavior.
apps/backend/src/campaign/mutation.ts (4)
201-201: Helpful comment about cascade behavior.The comment clarifies the delete behavior, which is useful for understanding the data relationships.
391-391: Good function rename for clarity.Renaming
canceltocancelCampaignis more descriptive and follows better naming conventions, especially in a file that contains multiple mutation functions.
413-418: Excellent expansion of cancellable states.Allowing cancellation of campaigns in "CREATING", "SENDING", and "SCHEDULED" states provides much better user experience and covers all logical scenarios where cancellation should be possible.
420-440: Outstanding implementation of atomic cancellation.The transaction-based approach ensures data consistency by atomically updating both the campaign status and all related message statuses. This prevents partial updates and race conditions.
Key benefits:
- Atomicity ensures either all updates succeed or none do
- Proper filtering of message statuses prevents overwriting already processed messages
- Consistent state management across campaign and messages
This is a significant improvement over the previous non-atomic approach.
apps/backend/src/cron/processQueuedCampaigns.ts (5)
15-17: Good enhancement to function signature for list-based filtering.The addition of the
selectedListIdsparameter properly restricts subscriber selection to specific lists, which aligns with the campaign creation bug fix objective.
19-21: Excellent defensive programming with early return.The early return for empty
selectedListIdsprevents unnecessary database queries and correctly returns an empty result when no lists are selected.
28-28: Proper implementation of list-based filtering.The query correctly filters subscribers to only include those belonging to the specified lists using the
inoperator.
134-137: Function call correctly updated with new parameter.The function call properly passes the
selectedListIdsparameter, maintaining consistency with the updated function signature.
258-258: Consistent filtering logic applied to count query.The count query correctly uses the same
selectedListIdsfiltering logic as the main subscriber query, ensuring consistency between subscriber fetching and counting operations.
Summary by CodeRabbit
New Features
Bug Fixes
User Interface
Chores