Files
calendar/packages/features/webhooks/lib/tasker/trigger/deliver-webhook.ts
T
Syed Ali ShahbazGitHubali@cal.com <alishahbaz7@gmail.com>unknown <>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2ec9e903ce feat: implement webhook tasker with async/sync fallback (#27378)
* feat: implement webhook tasker with async/sync fallback

This PR implements a webhook tasker with async/sync fallback architecture
to fix failing E2E tests. The solution follows the existing proration
tasker pattern and uses Dependency Injection with @evyweb/ioctopus.

Key changes:
- Create IWebhookTasker interface for webhook delivery
- Implement WebhookSyncTasker for immediate execution (E2E tests)
- Implement WebhookAsyncTasker for queued execution (production)
- Create main WebhookTasker class extending Tasker<IWebhookTasker>
- Add DI modules and tokens for all tasker components
- Update WebhookTaskerProducerService to use new WebhookTasker
- Add unit tests for sync and async taskers

The ENABLE_ASYNC_TASKER flag automatically selects the appropriate mode:
- Production: Uses WebhookAsyncTasker to queue tasks
- E2E Tests: Uses WebhookSyncTasker for immediate execution

This ensures webhooks are delivered immediately in E2E tests without
requiring the cron job that processes queued tasks.

Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>

* fix: update WebhookTaskerProducerService tests for new interface

Update tests to use the new deps-based constructor and
mockWebhookTasker.deliverWebhook instead of mockTasker.create

Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>

* fix: use moduleLoader pattern for WebhookProducerService in container

Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>

* refactor: replace InternalTasker with Trigger.dev for webhook delivery

This commit refactors the WebhookTasker to use Trigger.dev instead of
InternalTasker, following the pattern established in BookingEmailAndSmsTasker
and PlatformOrganizationBillingTasker (PR #26803).

Changes:
- Replace WebhookAsyncTasker with WebhookTriggerTasker that uses trigger.dev
- Create trigger.dev task files (deliver-webhook.ts, config.ts, schema.ts)
- Update DI modules to use WebhookTriggerTasker
- Remove old InternalTasker-based implementation
- Update unit tests for new implementation

The WebhookSyncTasker continues to execute webhooks immediately for E2E tests
where ENABLE_ASYNC_TASKER is automatically false.

Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>

* fix: update comments to reflect Trigger.dev usage instead of InternalTasker

Co-Authored-By: unknown <>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-29 15:30:07 +04:00

49 lines
1.8 KiB
TypeScript

import { ErrorWithCode } from "@calcom/lib/errors";
import { logger, schemaTask, type TaskWithSchema } from "@trigger.dev/sdk";
import type { WebhookTaskPayload } from "../../types/webhookTask";
import { webhookDeliveryTaskConfig } from "./config";
import { webhookDeliveryTaskSchema } from "./schema";
const WEBHOOK_DELIVERY_JOB_ID = "webhook.deliver" as const;
/**
* Trigger.dev task for webhook delivery
*
* This task is triggered by WebhookTriggerTasker and processes webhook
* delivery using the WebhookTaskConsumer from the DI container.
*
* The task:
* 1. Imports the DI container getter
* 2. Gets the WebhookTaskConsumer instance
* 3. Calls processWebhookTask with the payload
*
* Errors are logged and re-thrown to enable trigger.dev's retry mechanism.
*/
export const deliverWebhook: TaskWithSchema<typeof WEBHOOK_DELIVERY_JOB_ID, typeof webhookDeliveryTaskSchema> =
schemaTask({
id: WEBHOOK_DELIVERY_JOB_ID,
...webhookDeliveryTaskConfig,
schema: webhookDeliveryTaskSchema,
run: async (payload: WebhookTaskPayload, { ctx }) => {
const { getWebhookTaskConsumer } = await import(
"@calcom/features/di/webhooks/containers/webhook"
);
const webhookTaskConsumer = getWebhookTaskConsumer();
const taskId = ctx.run.id;
try {
await webhookTaskConsumer.processWebhookTask(payload, taskId);
logger.info("Webhook delivered successfully", { operationId: payload.operationId, taskId });
} catch (error) {
if (error instanceof Error || error instanceof ErrorWithCode) {
logger.error(error.message, { operationId: payload.operationId, taskId });
} else {
logger.error("Unknown error in webhook delivery", { error, operationId: payload.operationId, taskId });
}
throw error;
}
},
});