# Asynchronní přenos leadů z Next.js do 1C Bitrix: vzorec bez front a workerů
Synchronní odesílání leadů do CRM přes REST API vede k kritickým problémům: uživatel čeká na odpověď až do dokončení externího požadavku, nestabilita API 1C Bitrix způsobuje timeouty a chyby. Nabízíme řešení na Next.js 16, které vylučuje fronty a pozadíové procesy. Implementace ukládá lead do lokální PostgreSQL, okamžitě odpovídá uživateli a integraci s Bitrixem provádí přes after() – mechanismus pozadíového zpracování po odeslání HTTP odpovědi.
Architektura bez front: tři vrstvy odpovědnosti
Klíčový princip – rozdělení operací na synchronní a asynchronní části. Při přijetí formuláře:
- Validace dat přes zod
- Uložení do PostgreSQL s bitrix_id=NULL
- Okamžitá odpověď 200 OK
- Pozadíové odeslání do Bitrix přes after()
To zaručuje:
- Nezávislost na stabilitě Bitrix REST API
- Absence blokování uživatelského rozhraní
- Možnost manuálního zpracování nedoručených leadů přes SELECT * FROM leads WHERE bitrix_id IS NULL
Výhodou přístupu je odmítnutí Redis/BullMQ. Všechny operace se vejdou do API route Next.js, používajíc vestavěný after() pro post-odpovědní zpracování. To snižuje složitost infrastruktury a zjednodušuje nasazení na VPS přes systemd/nginx.
after() v Next.js 16: technická implementace
Metoda after() řeší problém „ogň-and-forget“ v serverless prostředích. Na rozdíl od Promise.resolve().then() zaručuje provedení úlohy i po odeslání odpovědi, bez ukončení procesu před dokončením operace. Příklad zpracování formuláře:
export async function POST(request: Request) {
// ... validatsiya and antidubl
const [lead] = await pgQuery(...);
after(async () => {
try {
const bitrixId = await sendToBitrix24(payload);
await pgQuery(
`UPDATE leads SET bitrix_id = $1 WHERE id = $2`,
[bitrixId, lead.id]
);
} catch (error) {
console.error("[Leads API] Error otpravki in Bitriks:", error);
}
});
return Response.json({ ok: true, id: lead.id });
}
Důležité nuancí:
- Anti-duplicita je realizována přes okno 10 minut v PostgreSQL, ne přes Bitrix (CRM přijímá duplicity bez varování)
- bitrix_id je uloženo jako nullable text – odráží asynchronní povahu operace
- Chyby integrace se logují do journalctl, neovlivňují uživatelskou odpověď
Spolehlivý HTTP klient pro 1C Bitrix
Kritické parametry pro stabilní práci s nestabilním API:
- MAX_ATTEMPTS = 2 – rovnováha mezi spolehlivostí a zátěží
- REQUEST_TIMEOUT_MS = 8000 – nad p95 latencí Bitrix (400-700 ms)
- RETRY_DELAY_MS = 1500 – lineární backoff bez exponenciální složitosti
Implementace klienta zahrnuje:
async function bitrixRequest(method: string, payload: Record<string, unknown>) {
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
try {
const response = await fetch(url, {
signal: controller.signal,
// ...
});
const text = await response.text();
const json = text ? JSON.parse(text) : {};
if (!response.ok || json.error) {
throw new Error(json.error_description || `HTTP ${response.status}`);
}
return json;
} catch (error) {
if (attempt >= MAX_ATTEMPTS) throw error;
await new Promise(r => setTimeout(r, RETRY_DELAY_MS));
} finally {
clearTimeout(timer);
}
}
}
Tři klíčové momenty:
- Manuální parsování přes response.text() místo response.json() – obchází chyby Bitrix s prázdnými odpověďmi
- Zpracování dvou typů chyb: HTTP statusy a interní chyby CRM
- Zaručené vyčištění timeru v finally – zabraňuje únikům paměti
Vlastnosti autentizace a schématu dat
Pro integraci byl vybrán incoming webhook místo OAuth:
- Žádná závislost na Marketplace a schvalováních
- Jednoduché řízení env proměnné BITRIX_WEBHOOK_URL
- Scopy se nastavují v admince Bitrix
Riziko úniku tokenu v URL se minimalizuje pravidlem: v logách a kódu se uvádí jen metoda API, ne úplná URL.
Schématu tabulky leads:
CREATE TABLE leads (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
name text NOT NULL,
phone text NOT NULL,
source text,
bitrix_id text,
created_at timestamptz NOT NULL DEFAULT now()
);
Proč bitrix_id text, ne integer?
- Bitrix vrací ID jako řetězec v JSON
- Není potřeba převodu typů
- UUID v PostgreSQL zajišťuje idempotenci
Co je důležité
- Zdroj pravdy – lokální DB: lead se ukládá před voláním Bitrixu, což zaručuje data i při selhání CRM
- Post-odesílací zpracování: after() nahrazuje fronty, odstraňuje složitost infrastruktury
- Řízení chyb: retry s timeouty a logování do journalctl zajišťuje pozorovatelnost
- Anti-duplicita na úrovni DB: okno 10 minut podle telefonu zabraňuje duplicitám nezávisle na CRM
- Bezpečná autentizace: webhook vyžaduje přísnou kontrolu logování URL
Tento vzorec je vhodný pro projekty s zatížením do 50 požadavků za minutu. Pro vysoce zatížené systémy se doporučuje přidat monitorování přes SELECT COUNT(*) FROM leads WHERE bitrix_id IS NULL a automatické retry přes cron. V aktuální implementaci je manuální zpracování chyb preferováno před automatickými opakovanými pokusy – to snižuje riziko duplikování leadů při dočasných selháních.
— Editorial Team
Zatím žádné komentáře.