𝗠𝘆 𝗔𝗣𝗜 𝗕𝗿𝗼𝗸𝗲 𝗘𝘃𝗲𝗿𝘆 𝗝𝗮𝗻𝘂𝗮𝗿𝘆 𝟭𝘀𝘁
मेरी API ठीक 1 जनवरी को 00:00 UTC पर खराब हो गई थी।
यह उपयोगकर्ताओं की आधी रात पर खराब नहीं हुई थी। यह UTC आधी रात पर खराब हुई थी। टोक्यो के उपयोगकर्ताओं ने अपने समय के अनुसार सुबह 9 बजे से खराब डेटा देखा।
टेस्ट पास हो गए थे। स्टेजिंग एनवायरनमेंट (staging environment) सही काम कर रहा था। एरर केवल प्रोडक्शन में था क्योंकि प्रोडक्शन सर्वर स्टेजिंग की तुलना में अलग टाइमज़ोन का उपयोग कर रहा था।
समस्या इस लॉजिक में थी:
function getDailyReport(date) {
const start = new Date(date).toISOString().split('T')[0];
const end = new Date(start + 'T23:59:59Z');
return db.reports.findMany({
where: {
createdAt: { gte: new Date(start), lt: end }
}
});
}
जब आप बिना समय के "2026-01-01" जैसी तारीख पास करते हैं, तो सिस्टम लोकल टाइमज़ोन का उपयोग करता है।
हमारा स्टेजिंग सर्वर UTC का उपयोग करता था। हमारा प्रोडक्शन सर्वर US-East का उपयोग करता था। इससे हर एक डेट क्वेरी (date query) पर पांच घंटे का ऑफसेट (offset) बन गया।
हमने हर क्वेरी पर पांच घंटे का डेटा खो दिया। आंकड़े इतने करीब लग रहे थे कि पूरे एक साल तक किसी ने ध्यान नहीं दिया।
समाधान सरल था। स्ट्रिंग में समय जोड़कर UTC को अनिवार्य (force) करें:
function getDailyReport(date: string) {
const start = new Date(`${date}T00:00:00Z`);
const end = new Date(`${date}T23:59:59.999Z`);
return db.reports.findMany({
where: {
createdAt: { gte: start, lt: end }
}
});
}
कोड बदलने में कुछ ही सेकंड लगे। सिस्टम को ठीक करने में एक सप्ताह लगा। हमने ये चार काम किए:
• CI में एक टाइमज़ोन एसर्शन (timezone assertion) जोड़ा ताकि यह सुनिश्चित हो सके कि एनवायरनमेंट UTC में ही रहे। • हर कंटेनर को एक जैसा रखने के लिए सभी Dockerfiles में TZ=UTC सेट किया। • डिप्लॉय स्क्रिप्ट (deploy script) में एक टाइमज़ोन चेक जोड़ा। • किसी भी ऐसे Date constructor को फ्लैग करने के लिए एक लिंटर रूल (linter rule) लिखा जिसमें टाइमज़ोन की जानकारी नहीं थी।
टाइमज़ोन बग्स खतरनाक होते हैं। वे आपके सिस्टम को क्रैश नहीं करते। वे गलत डेटा देते हैं जो सही दिखता है। आपके उपयोगकर्ताओं को एरर पेज नहीं दिखेगा। उन्हें गलत आंकड़े दिखेंगे और वे उन पर भरोसा करेंगे।
इन तीन नियमों का पालन करें:
- सिस्टम टाइमज़ोन पर कभी भरोसा न करें। हमेशा TZ=UTC सेट करें।
- बिना टाइमज़ोन के तारीखों को कभी पार्स (parse) न करें।
- कभी यह न मानें कि आपका CI टाइमज़ोन प्रोडक्शन से मेल खाता है।