mirror of
https://github.com/Luchexx/wacrm.git
synced 2026-11-02 17:29:45 +00:00
Merge pull request #303 from ArnasDon/fix/webhook-after-processing
fix(webhook): process inbound WhatsApp messages in after() so they survive serverless freeze (#301)
This commit is contained in:
commit
39aeac8c0c
@ -1,4 +1,4 @@
|
|||||||
import { NextResponse } from 'next/server'
|
import { NextResponse, after } from 'next/server'
|
||||||
import { createClient } from '@supabase/supabase-js'
|
import { createClient } from '@supabase/supabase-js'
|
||||||
import { decrypt, encrypt, isLegacyFormat } from '@/lib/whatsapp/encryption'
|
import { decrypt, encrypt, isLegacyFormat } from '@/lib/whatsapp/encryption'
|
||||||
import { getMediaUrl, downloadMedia } from '@/lib/whatsapp/meta-api'
|
import { getMediaUrl, downloadMedia } from '@/lib/whatsapp/meta-api'
|
||||||
@ -12,6 +12,12 @@ import {
|
|||||||
isTemplateWebhookField,
|
isTemplateWebhookField,
|
||||||
} from '@/lib/whatsapp/template-webhook'
|
} from '@/lib/whatsapp/template-webhook'
|
||||||
|
|
||||||
|
// The `after()` callback in POST runs within this route's max duration.
|
||||||
|
// Inbound processing can fan out to per-media Meta verification calls, so
|
||||||
|
// give it headroom beyond the platform default (Vercel clamps this to the
|
||||||
|
// plan's ceiling). Tune as needed.
|
||||||
|
export const maxDuration = 60
|
||||||
|
|
||||||
// Lazy-initialized to avoid build-time crash when env vars are missing
|
// Lazy-initialized to avoid build-time crash when env vars are missing
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
let _adminClient: any = null
|
let _adminClient: any = null
|
||||||
@ -182,9 +188,26 @@ export async function POST(request: Request) {
|
|||||||
return NextResponse.json({ error: 'Invalid JSON' }, { status: 400 })
|
return NextResponse.json({ error: 'Invalid JSON' }, { status: 400 })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process asynchronously so we can ack Meta within their timeout.
|
// Process AFTER the response so we ack Meta within their ~20s timeout
|
||||||
processWebhook(body).catch((error) => {
|
// (a slow ack triggers Meta retries + duplicate inserts), while still
|
||||||
console.error('Error processing webhook:', error)
|
// guaranteeing the work runs to completion.
|
||||||
|
//
|
||||||
|
// This MUST use `after()` rather than a detached `processWebhook(body)`
|
||||||
|
// promise: on serverless platforms (we run on Vercel) the function can
|
||||||
|
// be frozen or terminated the moment the response is sent, so a floating
|
||||||
|
// promise's DB writes are not guaranteed to finish. That dropped a
|
||||||
|
// non-deterministic *subset* of inbound messages — contacts/conversations
|
||||||
|
// were created but the message insert never landed, leaving conversations
|
||||||
|
// that show in the inbox with an empty thread, and no logs to explain it
|
||||||
|
// (see issue #301). `after()` hands the callback to the runtime, which
|
||||||
|
// keeps the function alive until it resolves (within the route's
|
||||||
|
// maxDuration).
|
||||||
|
after(async () => {
|
||||||
|
try {
|
||||||
|
await processWebhook(body)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error processing webhook:', error)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return NextResponse.json({ status: 'received' }, { status: 200 })
|
return NextResponse.json({ status: 'received' }, { status: 200 })
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user