Skip to content

Commit 5028930

Browse files
fix(webhooks): immediate acks only for teams (#788)
1 parent b565bab commit 5028930

File tree

1 file changed

+107
-53
lines changed

1 file changed

+107
-53
lines changed

apps/sim/lib/webhooks/utils.ts

Lines changed: 107 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,104 @@ export async function fetchAndProcessAirtablePayloads(
14371437
/**
14381438
* Process webhook verification and authorization
14391439
*/
1440+
/**
1441+
* Handle Microsoft Teams webhooks with immediate acknowledgment
1442+
*/
1443+
async function processMicrosoftTeamsWebhook(
1444+
foundWebhook: any,
1445+
foundWorkflow: any,
1446+
input: any,
1447+
executionId: string,
1448+
requestId: string
1449+
): Promise<NextResponse> {
1450+
logger.info(
1451+
`[${requestId}] Acknowledging Microsoft Teams webhook ${foundWebhook.id} and executing workflow ${foundWorkflow.id} asynchronously (Execution: ${executionId})`
1452+
)
1453+
1454+
// Execute workflow asynchronously without waiting for completion
1455+
executeWorkflowFromPayload(
1456+
foundWorkflow,
1457+
input,
1458+
executionId,
1459+
requestId,
1460+
foundWebhook.blockId
1461+
).catch((error) => {
1462+
// Log any errors that occur during async execution
1463+
logger.error(
1464+
`[${requestId}] Error during async workflow execution for webhook ${foundWebhook.id} (Execution: ${executionId})`,
1465+
error
1466+
)
1467+
})
1468+
1469+
// Return immediate acknowledgment for Microsoft Teams
1470+
return NextResponse.json(
1471+
{
1472+
type: 'message',
1473+
text: 'Sim Studio',
1474+
},
1475+
{ status: 200 }
1476+
)
1477+
}
1478+
1479+
/**
1480+
* Handle standard webhooks with synchronous execution
1481+
*/
1482+
async function processStandardWebhook(
1483+
foundWebhook: any,
1484+
foundWorkflow: any,
1485+
input: any,
1486+
executionId: string,
1487+
requestId: string
1488+
): Promise<NextResponse> {
1489+
logger.info(
1490+
`[${requestId}] Executing workflow ${foundWorkflow.id} for webhook ${foundWebhook.id} (Execution: ${executionId})`
1491+
)
1492+
1493+
await executeWorkflowFromPayload(
1494+
foundWorkflow,
1495+
input,
1496+
executionId,
1497+
requestId,
1498+
foundWebhook.blockId
1499+
)
1500+
1501+
// Since executeWorkflowFromPayload handles logging and errors internally,
1502+
// we just need to return a standard success response for synchronous webhooks.
1503+
// Note: The actual result isn't typically returned in the webhook response itself.
1504+
1505+
return NextResponse.json({ message: 'Webhook processed' }, { status: 200 })
1506+
}
1507+
1508+
/**
1509+
* Handle webhook processing errors with provider-specific responses
1510+
*/
1511+
function handleWebhookError(
1512+
error: any,
1513+
foundWebhook: any,
1514+
executionId: string,
1515+
requestId: string
1516+
): NextResponse {
1517+
logger.error(
1518+
`[${requestId}] Error in processWebhook for ${foundWebhook.id} (Execution: ${executionId})`,
1519+
error
1520+
)
1521+
1522+
// For Microsoft Teams outgoing webhooks, return the expected error format
1523+
if (foundWebhook.provider === 'microsoftteams') {
1524+
return NextResponse.json(
1525+
{
1526+
type: 'message',
1527+
text: 'Webhook processing failed',
1528+
},
1529+
{ status: 200 }
1530+
) // Still return 200 to prevent Teams from showing additional error messages
1531+
}
1532+
1533+
return new NextResponse(`Internal Server Error: ${error.message}`, {
1534+
status: 500,
1535+
})
1536+
}
1537+
14401538
export async function processWebhook(
14411539
foundWebhook: any,
14421540
foundWorkflow: any,
@@ -1449,11 +1547,7 @@ export async function processWebhook(
14491547
// --- Handle Airtable differently - it should always use fetchAndProcessAirtablePayloads ---
14501548
if (foundWebhook.provider === 'airtable') {
14511549
logger.info(`[${requestId}] Routing Airtable webhook through dedicated processor`)
1452-
1453-
// Use the dedicated Airtable payload fetcher and processor
14541550
await fetchAndProcessAirtablePayloads(foundWebhook, foundWorkflow, requestId)
1455-
1456-
// Return standard success response
14571551
return NextResponse.json({ message: 'Airtable webhook processed' }, { status: 200 })
14581552
}
14591553

@@ -1475,60 +1569,20 @@ export async function processWebhook(
14751569
return new NextResponse('No messages in WhatsApp payload', { status: 200 })
14761570
}
14771571

1478-
// --- Send immediate acknowledgment and execute workflow asynchronously ---
1479-
logger.info(
1480-
`[${requestId}] Acknowledging webhook ${foundWebhook.id} and executing workflow ${foundWorkflow.id} asynchronously (Execution: ${executionId})`
1481-
)
1482-
1483-
// Execute workflow asynchronously without waiting for completion
1484-
executeWorkflowFromPayload(
1485-
foundWorkflow,
1486-
input,
1487-
executionId,
1488-
requestId,
1489-
foundWebhook.blockId
1490-
).catch((error) => {
1491-
// Log any errors that occur during async execution
1492-
logger.error(
1493-
`[${requestId}] Error during async workflow execution for webhook ${foundWebhook.id} (Execution: ${executionId})`,
1494-
error
1495-
)
1496-
})
1497-
1498-
// Return immediate acknowledgment to the webhook provider
1499-
// For Microsoft Teams outgoing webhooks, return the expected response format
1572+
// --- Route to appropriate processor based on provider ---
15001573
if (foundWebhook.provider === 'microsoftteams') {
1501-
return NextResponse.json(
1502-
{
1503-
type: 'message',
1504-
text: 'Sim Studio',
1505-
},
1506-
{ status: 200 }
1574+
return await processMicrosoftTeamsWebhook(
1575+
foundWebhook,
1576+
foundWorkflow,
1577+
input,
1578+
executionId,
1579+
requestId
15071580
)
15081581
}
15091582

1510-
return NextResponse.json({ message: 'Webhook received' }, { status: 200 })
1583+
return await processStandardWebhook(foundWebhook, foundWorkflow, input, executionId, requestId)
15111584
} catch (error: any) {
1512-
// Catch errors *before* calling executeWorkflowFromPayload (e.g., auth errors)
1513-
logger.error(
1514-
`[${requestId}] Error in processWebhook *before* execution for ${foundWebhook.id} (Execution: ${executionId})`,
1515-
error
1516-
)
1517-
1518-
// For Microsoft Teams outgoing webhooks, return the expected error format
1519-
if (foundWebhook.provider === 'microsoftteams') {
1520-
return NextResponse.json(
1521-
{
1522-
type: 'message',
1523-
text: 'Request received but processing failed',
1524-
},
1525-
{ status: 200 }
1526-
) // Still return 200 to prevent Teams from showing additional error messages
1527-
}
1528-
1529-
return new NextResponse(`Internal Server Error: ${error.message}`, {
1530-
status: 500,
1531-
})
1585+
return handleWebhookError(error, foundWebhook, executionId, requestId)
15321586
}
15331587
}
15341588

0 commit comments

Comments
 (0)