Қысқаша
Счёттар біреуден емес, топтап құлап жатса, бірінші істейтін нәрсе — жіберуді тоқтату. Себебі көбіне жиілікте: бір кассир арқылы қысқа уақытта тым көп сұрау кеткен. Kaspi кассирдің сұрау жиілігін шектеуі мүмкін, ал біз құлаған счётты өз бетімізше қайта жібермейміз — қайталау сіздің кодыңыздың міндеті. Сондықтан циклді тоқтатып, қате кодына қарап, кезекпен қайта жіберу керек.
Ең қауіптісі — қате келген сайын бірден қайталайтын код. Ол жағдайды тек нашарлатады және тәуліктік қорғаныс шегіне жеткізеді.
Алдымен тоқтатыңыз
Жаппай құлау кезінде реті осындай:
- Жіберетін процесті тоқтатыңыз. Cron, кезек, скрипт — не болса да.
- Соңғы 50 қатенің
errorкодын жинаңыз. Бәрі бірдей ме, әлде әртүрлі ме — шешім осыған байланысты. - Бір ғана счётты қолмен жіберіп көріңіз. Ол өтсе, мәселе жиілікте. Ол да құласа, мәселе басқада.
- Кабинеттен қолмен счёт шығарыңыз. Ол шықса, Kaspi байланысы тірі.
Шұғыл жағдайда, мысалы код циклге түсіп кеткені белгілі болса, ең сенімді тоқтатқыш — кабинеттен сол API кілтті жою. Кілт жойылған соң бірде-бір счёт жасалмайды. Жаңа кілт кейін жасайсыз.
Қате кодына қарап ажырату
error | Нені білдіреді | Не істеу керек |
|---|---|---|
rate_limited, request_rate_limited | Сұрау жиілігі шектен асты | Retry-After тақырыбын оқып, сонша күтіңіз |
too_many_attempts | Бір әрекетті тым жиі қайталадыңыз | Бір минут күтіңіз |
tariff_daily_burst | Тәуліктік қорғаныс іске қосылды | Бұл бизнес лимиті емес. Кодта цикл бар ма, қараңыз |
tariff_limit_reached | Тарифтің айлық счёт лимиті бітті | Тарифті көтеріңіз немесе жаңа айды күтіңіз |
invoice_create_failed | Kaspi счётты қабылдамады | Кідіріспен қайталауға болады |
kaspi_session_expired | Кассир байланысы үзілген | Кассирді қайта байланыстырыңыз |
insufficient_scope, tariff_inactive | Құқық немесе тариф мәселесі | API 403 қайтарады |
unauthorized | Кілт танылмады | API 401 қайтарады |
Бәрі бірдей код болса — себебі біреу, оны түзету жеңіл. Кодтар аралас болса — көбіне жиілік: жүйе әртүрлі жерден қайтарып жатыр.
tariff_daily_burst пен tariff_limit_reached екеуін шатастырмаңыз. Біріншісі — тәуліктік қорғаныс, әдетте кодтағы циклдің салдары. Екіншісі — сіздің тарифіңіздің айлық лимиті, яғни нағыз бизнес көрсеткіші.
Автоматты қайталау жоқ
Мұны нақты білген жөн: счёт жасау сұрауы құласа, біз оны өзіміз қайта жібермейміз. Бұл әдейі істелген — сіздің рұқсатыңызсыз қайталасақ, клиентке екі рет счёт барып қалуы мүмкін.
Қайталау сіздің жағыңызда болуы керек, әрі мынадай ережемен:
- Қайталау кідірісі өсіп отырсын. 1, 2, 4, 8, 16 секунд. Бірден қайталау ешқашан көмектеспейді.
- Қайталау саны шектеулі болсын. Үш-бес талпыныс, одан кейін кезекке қалдырып, ескерту жіберіңіз.
- 4xx қателерді қайталамаңыз. Сома дұрыс емес болса, оны жүз рет жіберсеңіз де қабылданбайды.
Idempotency-Keyжіберіңіз. Сонда қайталағанда жаңа счёт жасалмай, бұрынғысы қайтады.
const res = await fetch('https://api.qut.kz/api/v1/invoices', {
method: 'POST',
headers: {
'X-API-Key': key,
'Content-Type': 'application/json',
'Idempotency-Key': `order-${orderId}`,
},
body: JSON.stringify({ amount, description, externalOrderId: String(orderId) }),
});
Idempotency-Key ретінде өз тапсырыс нөміріңізді алыңыз — сонда қайталау қауіпсіз болады, счёт екеу болып кетпейді.
Кезекпен жіберу
Жүз счётты бір секундта жіберудің қажеті жоқ. Кассир — Kaspi-дегі бір ғана рөл, оның да сұрау жиілігі шектеулі.
Практикада жұмыс істейтін тәсіл:
async function sendQueue(orders) {
const failed = [];
for (const order of orders) {
try {
await createInvoice(order);
} catch (e) {
failed.push({ order, error: e.code });
if (e.code === 'rate_limited' || e.code === 'tariff_daily_burst') {
await sleep(60_000); // бір минут пауза, сосын жалғастырамыз
}
}
await sleep(300); // счёттар арасында шағын кідіріс
}
return failed;
}
Негізгі үш ұстаным:
- Біртіндеп жіберіңіз, қатар емес. Он ағынмен қатар жіберу — жаппай құлаудың ең жиі себебі.
- Счёттар арасында кідіріс қалдырыңыз. Бірнеше жүз миллисекунд жеткілікті.
- Бірінші қатеде тоқтап, себебін оқыңыз. Соқыр жалғастыру — барлық тізімді жоғалту деген сөз.
Бір сұрауда бірнеше счёт керек болса, әрқайсысын бөлек жіберудің орнына POST /api/v1/invoices/bulk әдісін қолданыңыз: бір сұрауда 1-100 счёт, әрқайсысы бөлек тексеріледі, нәтижесінде қайсысы өтіп, қайсысы құлағанын бөлшектеп көресіз.
Жинақтау режимі
Тұрақты көп ағыны бар жүйелерде ең сенімді сұлба — жинақтап, біртіндеп жіберу:
- Счёт жасау керек әр оқиғаны бірден API-ға емес, өз кезегіңізге жазыңыз
- Бір ғана жұмысшы процесс сол кезектен алып, біртіндеп жібереді
- Құлағанын кезекте қалдырып, кідіріспен қайта жібереді
- Үш талпыныстан кейін де өтпесе, адамға ескерту кетеді
Бұл сұлбада шыңдар тегістеледі: клиенттер жүз тапсырыс берсе де, API-ға біркелкі ағын барады. Ал ең бастысы — жүйе құласа, тапсырыстар жоғалмай кезекте тұрады.
Қайталанбауы үшін
- Циклден қорғаныс қойыңыз. Бір тапсырыс бойынша бір ғана счёт жасалатынын кодта тексеріңіз.
externalOrderIdжіберіңіз. Сонда счёт қай тапсырыстікі екені webhook-та да көрінеді, қосарлануды бірден байқайсыз.- Журнал жазыңыз. Әр сұраудың уақыты, жауап коды,
errorмәні жазулы тұрсын. Мұнсыз себебін табу мүмкін емес. - Тәуліктік санды бақылаңыз. Тарифіңіздің тәуліктік қорғаныс шегіне жақындап қалсаңыз, кодта цикл бар-жоғын тексеріңіз.
Жиі қойылатын сұрақтар
Құлаған счёттар кейін өзі жасала ма? Жоқ. Қайта жіберу — сіздің міндетіңіз.
Тәуліктік қорғанысқа тірелдім, қалай алып тастауға болады? Ол уақыт өтісімен өзі босайды. Бірақ алдымен себебін табыңыз: көп жағдайда кодта цикл бар.
Бір мезетте қанша счёт жіберуге болады? Нақты сан жоқ: шектеу жағдайға байланысты. Практикада бір-бірден, арасында шағын кідіріспен жіберу ешқашан мәселе тудырмайды.
Бірнеше кассир қоссам, жылдамдық артады ма? Жүктеме бөлінеді, бірақ бұл негізгі шешім емес. Алдымен жіберу логикасын реттеңіз.
Мәселе менде емес, Kaspi-де деп қалай білемін? Екі минуттық диагностика бар: Мәселе менде ме, Kaspi-де ме.