Skip to content

refactor(bookings): move post booking side effects to background jobs#1973

Open
cal-id-actions[bot] wants to merge 2 commits into
mainfrom
booking_optimizations
Open

refactor(bookings): move post booking side effects to background jobs#1973
cal-id-actions[bot] wants to merge 2 commits into
mainfrom
booking_optimizations

Conversation

@cal-id-actions
Copy link
Copy Markdown

@cal-id-actions cal-id-actions Bot commented May 26, 2026

Summary

Refactored the booking post-commit side effects to be handled asynchronously via background jobs, improving performance and reliability.

Changes

  • Moved booking post-commit integrations, scheduling, and webhook side effects into separate background job processors
  • Updated booking handling logic to enqueue background jobs instead of running side effects inline
  • Added new services and processors for booking post-commit jobs
  • Improved test coverage for booking post-commit job services and processors
  • Minor fixes and improvements in Inngest API handling and webhook payload sending

Testing Notes

  • Run booking creation and verify that side effects (integrations, scheduling, webhooks) are executed asynchronously
  • Confirm background jobs are enqueued and processed correctly
  • Run updated and new tests for booking post-commit job services and processors
  • Validate Inngest API endpoints and webhook payload delivery remain functional

@cal-id-actions cal-id-actions Bot added the main Auto PR target: main label May 26, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 26, 2026

Greptile Summary

This PR moves all post-booking side effects (webhooks, workflow reminders, integrations, analytics) from inline synchronous execution inside handleNewBooking to three dedicated BullMQ background jobs (BOOKING_POST_COMMIT_WEBHOOKS, BOOKING_POST_COMMIT_INTEGRATIONS, BOOKING_POST_COMMIT_SCHEDULING). Serialization helpers are added to make the CalendarEvent and webhook payload JSON-safe for the queue.

  • Core dispatch (handleNewBooking.ts): side-effect code removed; three jobs dispatched via Promise.allSettled when !isDryRun, with logging on individual dispatch failures.
  • Three new job services (job-engine): each handles one concern — webhooks/meeting triggers, integrations (push/chat/CIO/analytics), and scheduling (workflow reminders/no-show triggers) — using ctx.run steps with per-step error logging.
  • Type system (type.ts, serializeCalendarEventForInngest.ts): BookingPostCommitPayload and Serialized*ForQueue types added to model the JSON-safe job payload.

Confidence Score: 3/5

Not safe to merge as-is: the integrations service references a non-existent field isRescheduleEvent that will fail TypeScript compilation and silently deliver wrong push notification titles for rescheduled bookings.

The isRescheduleEvent reference in getMobileNotificationTitle does not exist on the payload type — TypeScript's Pick constraint will reject it at compile time, blocking a build. At runtime the push notification for every rescheduled booking would display 'booking_created' instead of 'booking_rescheduled'. Separately, a debug console.log was left inside the Customer.io identify path. The no-retry dispatch configuration and the missing SleepSignal guards in the new processors compound the risk on the critical booking path.

packages/job-engine/src/default/bookingPostCommitIntegrations.service.ts (type error + wrong notification title) and packages/features/bookings/lib/handleNewBooking/emitCioIdentifyForBookedHosts.ts (stray console.log) need fixes before merging.

Important Files Changed

Filename Overview
packages/job-engine/src/default/bookingPostCommitIntegrations.service.ts New service for post-booking integrations (mobile push, chat sync, CIO, contact sync, analytics); has a TypeScript compilation error — isRescheduleEvent referenced in getMobileNotificationTitle doesn't exist in the payload type, causing wrong push-notification titles for rescheduled bookings.
packages/features/bookings/lib/handleNewBooking/emitCioIdentifyForBookedHosts.ts Minor change — adds a debug console.log("Identifying on cio") that was accidentally left in production code.
packages/features/bookings/lib/handleNewBooking.ts Core refactor: removes all inline post-commit side effects and replaces them with three dispatched background jobs; correctly gates dispatch behind !isDryRun; all three jobs use attempts: 1 (no retry on failure).
packages/job-engine/src/default/bookingPostCommitWebhooks.service.ts New service reconstructing translation functions from serialized locale data and then delegating to existing webhook helpers; logic follows the original synchronous flow correctly.
packages/job-engine/src/default/bookingPostCommitScheduling.service.ts New service scheduling workflow reminders, mandatory reminders, and no-show triggers; straightforward extraction of the original synchronous logic into ctx.run steps.
packages/features/bookings/lib/handleNewBooking/buildPostCommitJobs.ts New helper that builds the shared serializable payload dispatched to all three post-commit jobs; correctly serializes Date fields to ISO strings and avoids passing non-serializable translate functions.
packages/job-engine/src/default/type.ts Adds BookingPostCommitPayload and three derived job data interfaces; isRescheduleEvent is absent (only rescheduleUid exists) — the missing field is the source of the bug in the integrations service.
apps/worker/src/workers/default.worker.ts Registers the three new processors in the default worker switch statement; follows existing patterns correctly but the corresponding processor files omit the SleepSignal guard convention.

Sequence Diagram

sequenceDiagram
    participant Client
    participant handleNewBooking
    participant DB as Database
    participant Dispatcher as Job Dispatcher (BullMQ)
    participant W1 as Worker: Webhooks Job
    participant W2 as Worker: Integrations Job
    participant W3 as Worker: Scheduling Job

    Client->>handleNewBooking: POST /booking
    handleNewBooking->>DB: createBooking()
    handleNewBooking->>handleNewBooking: buildPostCommitPayload()
    Note over handleNewBooking: Only if !isDryRun
    handleNewBooking->>Dispatcher: dispatch BOOKING_POST_COMMIT_WEBHOOKS
    handleNewBooking->>Dispatcher: dispatch BOOKING_POST_COMMIT_INTEGRATIONS
    handleNewBooking->>Dispatcher: dispatch BOOKING_POST_COMMIT_SCHEDULING
    handleNewBooking-->>Client: return booking response (fast)

    Note over Dispatcher,W3: Async background processing
    Dispatcher->>W1: process webhooks job
    W1->>W1: reconstructWebhookPayload
    W1->>W1: deleteWebhookScheduledTriggers (if reschedule)
    W1->>W1: scheduleTrigger (MEETING_STARTED/ENDED)
    W1->>W1: handleWebhookTrigger

    Dispatcher->>W2: process integrations job
    W2->>W2: sendMobileNotification
    W2->>W2: handleOHChatSync
    W2->>W2: emitCioIdentifyForBookedHosts
    W2->>W2: ensureCalIdContactFromBooking
    W2->>W2: handleAnalyticsEvents

    Dispatcher->>W3: process scheduling job
    W3->>W3: scheduleMandatoryReminder
    W3->>W3: scheduleWorkflowReminders
    W3->>W3: scheduleNoShowTriggers
Loading

Fix All in Claude Code Fix All in Codex

Reviews (1): Last reviewed commit: "Perf: Post booking side effects moved to..." | Re-trigger Greptile

Comment on lines +18 to +27
function getMobileNotificationTitle(
tOrganizer: (key: string) => string,
payload: Pick<BookingPostCommitIntegrationsJobData, "isConfirmedByDefault" | "isRescheduleEvent">
) {
if (!payload.isConfirmedByDefault) {
return tOrganizer("booking_requested");
}

return payload.isRescheduleEvent ? tOrganizer("booking_rescheduled") : tOrganizer("booking_created");
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 isRescheduleEvent does not exist on BookingPostCommitIntegrationsJobData (or BookingPostCommitPayload); the payload only carries rescheduleUid. This causes a TypeScript compilation error via Pick, and at runtime payload.isRescheduleEvent is always undefined, so rescheduled-booking push notifications will always show "booking_created" instead of "booking_rescheduled".

Suggested change
function getMobileNotificationTitle(
tOrganizer: (key: string) => string,
payload: Pick<BookingPostCommitIntegrationsJobData, "isConfirmedByDefault" | "isRescheduleEvent">
) {
if (!payload.isConfirmedByDefault) {
return tOrganizer("booking_requested");
}
return payload.isRescheduleEvent ? tOrganizer("booking_rescheduled") : tOrganizer("booking_created");
}
function getMobileNotificationTitle(
tOrganizer: (key: string) => string,
payload: Pick<BookingPostCommitIntegrationsJobData, "isConfirmedByDefault" | "rescheduleUid">
) {
if (!payload.isConfirmedByDefault) {
return tOrganizer("booking_requested");
}
return payload.rescheduleUid ? tOrganizer("booking_rescheduled") : tOrganizer("booking_created");
}

Fix in Claude Code Fix in Codex

Comment on lines +2225 to +2242
dispatcher.dispatch({
queue: QueueName.DEFAULT,
name: JobName.BOOKING_POST_COMMIT_WEBHOOKS,
data: { ...postCommitPayload, name: JobName.BOOKING_POST_COMMIT_WEBHOOKS },
bullmqOptions: { attempts: 1 },
}),
dispatcher.dispatch({
queue: QueueName.DEFAULT,
name: JobName.BOOKING_POST_COMMIT_INTEGRATIONS,
data: { ...postCommitPayload, name: JobName.BOOKING_POST_COMMIT_INTEGRATIONS },
bullmqOptions: { attempts: 1 },
}),
dispatcher.dispatch({
queue: QueueName.DEFAULT,
name: JobName.BOOKING_POST_COMMIT_SCHEDULING,
data: { ...postCommitPayload, name: JobName.BOOKING_POST_COMMIT_SCHEDULING },
bullmqOptions: { attempts: 1 },
}),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 All three post-commit jobs are dispatched with attempts: 1, which disables retries entirely. A single transient error (Redis timeout, downstream service blip) will permanently drop webhooks, scheduling triggers, or integrations with no chance of recovery. Consider using at least 3 attempts with exponential backoff.

Suggested change
dispatcher.dispatch({
queue: QueueName.DEFAULT,
name: JobName.BOOKING_POST_COMMIT_WEBHOOKS,
data: { ...postCommitPayload, name: JobName.BOOKING_POST_COMMIT_WEBHOOKS },
bullmqOptions: { attempts: 1 },
}),
dispatcher.dispatch({
queue: QueueName.DEFAULT,
name: JobName.BOOKING_POST_COMMIT_INTEGRATIONS,
data: { ...postCommitPayload, name: JobName.BOOKING_POST_COMMIT_INTEGRATIONS },
bullmqOptions: { attempts: 1 },
}),
dispatcher.dispatch({
queue: QueueName.DEFAULT,
name: JobName.BOOKING_POST_COMMIT_SCHEDULING,
data: { ...postCommitPayload, name: JobName.BOOKING_POST_COMMIT_SCHEDULING },
bullmqOptions: { attempts: 1 },
}),
dispatcher.dispatch({
queue: QueueName.DEFAULT,
name: JobName.BOOKING_POST_COMMIT_WEBHOOKS,
data: { ...postCommitPayload, name: JobName.BOOKING_POST_COMMIT_WEBHOOKS },
bullmqOptions: { attempts: 3, backoff: { type: "exponential", delay: 5000 } },
}),
dispatcher.dispatch({
queue: QueueName.DEFAULT,
name: JobName.BOOKING_POST_COMMIT_INTEGRATIONS,
data: { ...postCommitPayload, name: JobName.BOOKING_POST_COMMIT_INTEGRATIONS },
bullmqOptions: { attempts: 3, backoff: { type: "exponential", delay: 5000 } },
}),
dispatcher.dispatch({
queue: QueueName.DEFAULT,
name: JobName.BOOKING_POST_COMMIT_SCHEDULING,
data: { ...postCommitPayload, name: JobName.BOOKING_POST_COMMIT_SCHEDULING },
bullmqOptions: { attempts: 3, backoff: { type: "exponential", delay: 5000 } },
}),

Fix in Claude Code Fix in Codex

Comment on lines +6 to +9
export async function processBookingPostCommitWebhooks(job: Job<BookingPostCommitWebhooksJobData>) {
const ctx = createBullWorkflowContext(job);
await bookingPostCommitWebhooksService(ctx, job.data);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Missing SleepSignal guard

The apps/worker/AGENTS.md conventions require every processor to catch SleepSignal and return rather than rethrow. The three new processors omit this pattern entirely. If ctx.run() ever throws a SleepSignal internally, the job would fail instead of being paused and retried. The same gap applies to the other two processor files.

Fix in Claude Code Fix in Codex

@cal-id-actions cal-id-actions Bot changed the title refactor(bookings)!: move post booking side effects to background jobs refactor(bookings): move post booking side effects to background jobs May 27, 2026
@avnotaklu avnotaklu force-pushed the booking_optimizations branch 3 times, most recently from 554e8e0 to 7cc5155 Compare May 27, 2026 13:37
@avnotaklu avnotaklu force-pushed the booking_optimizations branch 2 times, most recently from e54ae78 to c7f1153 Compare May 28, 2026 05:59
@avnotaklu avnotaklu force-pushed the booking_optimizations branch from c7f1153 to 6270a41 Compare May 28, 2026 07:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

main Auto PR target: main

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant