𝗔 𝗦𝘂𝗰𝗰𝗲𝘀𝘀𝗳𝘂𝗹 𝗣𝗮𝘆𝗺𝗲𝗻𝘁 𝗧𝗵𝗮𝘁 𝗡𝗲𝘃𝗲𝗿 𝗕𝗲𝗰𝗮𝗺𝗲 𝗮 𝗕𝗼𝗼𝗸𝗶𝗻𝗴
ఒక కస్టమర్ చెల్లించారు. Razorpay విజయాన్ని చూపింది. Webhook ఒక HTTP 200 పంపింది. చెల్లింపు సక్సెస్ (captured) అయింది.
అయినప్పటికీ, బుకింగ్ "confirming" స్టేటస్లోనే ఆగిపోయింది.
ఎటువంటి ఎర్రర్స్ (errors) కనిపించలేదు. కోడ్ ఎక్కడా విఫలం కాలేదు (no exceptions). ఎటువంటి అలర్ట్స్ (alerts) రాలేదు. ప్రతి మెట్రిక్ కూడా సిస్టమ్ ఆరోగ్యంగానే ఉందని చూపించింది.
కానీ కస్టమర్కు ఏమీ అందలేదు. క్రియేటర్కు బుకింగ్ రాలేదు.
డబ్బును స్వీకరించడం సులభం. కానీ ప్రతి చెల్లింపు ఒక బుకింగ్కు దారితీసేలా చూడటమే అసలైన సవాలు.
చాలా ట్యుటోరియల్స్ ఈ ఫ్లోను సూచిస్తాయి:
- Webhook ఈవెంట్ను అందుకుంటుంది
- Webhook బుకింగ్ను అప్డేట్ చేస్తుంది
ఇది ప్రమాదకరం. ఒకవేళ బిజినెస్ లాజిక్ (business logic) వెబ్హుక్ లోపలే ఉంటే, మీరు పూర్తిగా డెలివరీ సక్సెస్ మీద ఆధారపడాల్సి వస్తుంది. వెబ్హుక్లు రీట్రైలు (retries), డూప్లికేట్లు (duplicates) మరియు పాక్షిక వైఫల్యాలను (partial failures) ఎదుర్కోవాల్సి ఉంటుంది.
ఈ పనులను వేరు చేయడానికి మేము మా ఆర్కిటెక్చర్ను మార్చాము. వెబ్హుక్లు ఇప్పుడు కేవలం ఈవెంట్లను మాత్రమే రికార్డ్ చేస్తాయి. అవి బిజినెస్ లాజిక్ను అమలు చేయవు.
మేము మూడు టేబుల్స్తో కూడిన ఒక ఈవెంట్ లెడ్జర్ను (event ledger) ప్రవేశపెట్టాము:
payment_orders: ప్రొవైడర్ యొక్క నిజం (The provider truth)payment_events: మార్చలేని ఈవెంట్ లెడ్జర్ (The immutable event ledger)bookings: బిజినెస్ యొక్క నిజం (The business truth)
వెబ్హుక్కు ఇప్పుడు ఒకే ఒక పని ఉంది:
- సిగ్నేచర్ను వెరిఫై చేయడం (Verify signature)
- ఈవెంట్ను స్టోర్ చేయడం (Store event)
- 200 రిటర్న్ చేయడం (Return 200)
ఇది సిస్టమ్ను రక్షిస్తుంది. ఒకవేళ వెబ్హుక్ విఫలమైనా, ఈవెంట్ సురక్షితంగా ఉంటుంది.
పేమెంట్ స్టేట్ (payment state) మరియు బుకింగ్ స్టేట్ (booking state) వేర్వేరు అని కూడా మేము తెలుసుకున్నాము. సక్సెస్ అయిన పేమెంట్ ఒక ఇన్పుట్ (input). కన్ఫర్మ్ అయిన బుకింగ్ ఒక ఫలితం (result). వీటిని విడివిడిగా ఉంచడం వల్ల రీకన్సిలియేషన్ (reconciliation) సులభమవుతుంది.
ఒక ఇన్వెస్టిగేషన్ సమయంలో, మేము ఒక బగ్ను (bug) కనుగొన్నాము. డేటాబేస్లో ఈవెంట్లు ఉన్నాయి. ప్రాసెసర్ (processor) ఆరోగ్యంగా ఉంది. వెబ్హుక్ కూడా ఆరోగ్యంగా ఉంది.
కానీ ప్రాసెసర్ ఎప్పుడూ రన్ కాలేదు. పెండింగ్లో ఉన్న ఈవెంట్లను ప్రాసెస్ చేయడానికి ఫంక్షన్ను ఎవరూ ట్రిగ్గర్ చేయడం లేదు.
ఇంగెషన్ (ingestion) నుండి ప్రాసెసింగ్ను వేరు చేయడం (decoupling) మంచి డిజైన్. కానీ ఇది ఒక కొత్త అవసరాన్ని సృష్టిస్తుంది: ప్రాసెసింగ్ను ఏదో ఒకటి ట్రిగ్గర్ చేయాలి.
మేము కొన్ని పనులను నిర్వహించడానికి ఒక షెడ్యూలర్ను (scheduler) అమలు చేశాము:
- పేమెంట్ ఈవెంట్లను ప్రాసెస్ చేయడం
- మిస్ అయిన వెబ్హుక్లను రికవరీ చేయడం
- సిస్టమ్ కన్సిస్టెన్సీని (system consistency) ధృవీకరించడం
రీట్రైల సమయంలో ఎర్రర్స్ రాకుండా ఉండటానికి, మేము ఈ లాజిక్ను ఉపయోగిస్తాము:
- ప్రాసెస్ చేయని ఈవెంట్లను ఎంచుకోవడం (Select unprocessed events)
- మల్టిపుల్ వర్కర్లకు అనుమతించడానికి
SKIP LOCKEDఉపయోగించడం - డూప్లికేట్ డెలివరీలు ఏమీ చేయకుండా చూడటం (Ensure duplicate deliveries do nothing)
ప్రతి వెబ్హుక్ సమయానికి వచ్చినప్పుడు మాత్రమే పనిచేసే సిస్టమ్ చాలా బలహీనమైనది (fragile). మీ క్యూ (queue) నుండి డేటాను తీసివేసే (drain) వారు ఎవరూ లేకపోతే, పని ఎప్పటికీ వేచి ఉంటుంది.
విశ్వసనీయత (Reliability) అంటే పరిస్థితులు విఫలమైనప్పుడు కూడా పనిచేసేలా నిర్మించడం.