পাবলিশের পরপরই ক্র্যাশ করা অ্যাপ ধরা
২৫ সেপ্টেম্বর তিনটি পাবলিশ সফল বলে চিহ্নিত হয়েছিল, যদিও অ্যাপের API প্রতিটি বুটের কয়েক সেকেন্ড পরেই ক্র্যাশ করছিল। ফলে কোনো রোলব্যাক চলেনি; কয়েক মিনিট পরে একটি ব্যাকগ্রাউন্ড যাচাই সেগুলোকে ব্যর্থ ঘোষণা করে, এবং পুরো সাইট একটি 404-তে চলে যায়। হেলথ চেক ক্র্যাশ গুনছিল হোস্টিং প্ল্যাটফর্মের ইভেন্ট তালিকায় — যেখানে প্রতি মেশিনে কেবল শেষ পাঁচটি ইভেন্ট থাকে। ক্র্যাশ লুপ সেই তালিকাটি সবসময় ভরাট রাখে, তাই গণনা কখনো বাড়ে না। এখন এটি সর্বশেষ ক্র্যাশের সময়ের সঙ্গে তুলনা করে, এবং ক্র্যাশ-লুপ করা পাবলিশ ব্যর্থ হয় ও আগের সংস্করণ ফিরিয়ে আনে।
পাবলিশ কীসের জন্য অপেক্ষা করে
যখন আপনি Mythex-এ একটি ব্যাকএন্ডসহ অ্যাপ পাবলিশ করেন, নতুন সংস্করণটি আমাদের হোস্টিং প্ল্যাটফর্মের মেশিনগুলোতে ছড়িয়ে দেওয়া হয়, এবং একটি হেলথ চেক ঠিক করে পাবলিশটি লাইভ হয়েছে নাকি ব্যর্থ হয়েছে। ব্যর্থ হলে একটি রোলব্যাক আগের সংস্করণ ফিরিয়ে আনে।
কঠিন অংশ হলো "শুরু হয়েছে" মানে "পরিবেশন করছে" নয়। প্ল্যাটফর্ম একটি মেশিনকে শুরু হয়েছে বলে জানায় যেই মুহূর্তে সেটি চালু হয়। যে অ্যাপ বুটের এক সেকেন্ড পরে ক্র্যাশ করে, সেটি সঙ্গে সঙ্গে আবার চালু হয়, এবং একটু পরেই আবার শুরু হয়েছে বলে দেখায়। তাই আমাদের হেলথ চেক সময়ের সঙ্গে কয়েকটি স্তরে বেড়েছে:
- দুবার দেখা। একটি মেশিন শুরু হয়েছে বলে দেখানোর পর অল্প সময় অপেক্ষা করে আবার দেখা হয়। বুটের সময়ের ক্র্যাশ প্রায়ই দ্বিতীয় দেখাতেই ধরা পড়ে।
- ক্র্যাশ লুপের দিকে নজর। প্ল্যাটফর্ম যদি জানায় যে একটি মেশিন বারবার ক্র্যাশ করেছে এবং এটিকে আবার চালু করা বন্ধ করেছে, তবে ব্যর্থ করা হয়।
- পাবলিশ শুরু হওয়ার পর থেকে ক্র্যাশ গোনা। দুটি "শুরু হয়েছে" দেখা একটি পুনরায় চালুর মাঝখানে পড়তে পারে। তাই পাবলিশ শুরুর পর থেকে কোনো ক্র্যাশ ঘটে থাকলে তৃতীয়বার দেখা হয়; আগের দেখার চেয়ে ক্র্যাশ বেশি হলে অ্যাপটি স্থির থাকছে না।
এই তৃতীয় চেকটিই এখানে ব্যর্থ হয়েছিল।
কেন সংখ্যাটি স্থির থাকছিল
ক্র্যাশের তথ্য আসে প্রতিটি মেশিনের ইভেন্ট তালিকা থেকে: শুরু, বন্ধ, পুনরায় চালু। প্ল্যাটফর্ম প্রতি মেশিনে কেবল শেষ পাঁচটি ইভেন্ট রাখে।
একটি অ্যাপ কল্পনা করুন যা বুটের ২.৫ সেকেন্ড পরে প্রতিবার ক্র্যাশ করে, যেমনটি তাদের একটি করছিল। প্রতিটি চক্র একটি ক্র্যাশ ও একটি শুরু যোগ করে। কয়েকটি চক্র পরে তালিকাটি ভরে যায়। তারপর থেকে প্রতিটি নতুন ইভেন্ট একটি পুরনো ইভেন্টকে ঠেলে বের করে দেয়। তালিকাটি সামনের দিকে সরে যায়, কিন্তু সবসময় প্রায় একই মিশ্রণ ধরে রাখে: কয়েকটি ক্র্যাশ, কয়েকটি শুরু।
তাই "পাবলিশ শুরুর পর কতগুলো ক্র্যাশ হয়েছে" প্রতিবার দেখায় একই সংখ্যা। দ্বিতীয় দেখায় হয়তো দুটি ক্র্যাশ ছিল। তৃতীয় দেখায়ও দুটি — ভিন্ন ক্র্যাশ, কিন্তু একই সংখ্যা। চেক ধরে নিল ক্র্যাশ থেমে গেছে, এবং পাবলিশটি পাস করিয়ে দিল।
এমন ঘটেছে ২৫ সেপ্টেম্বর তিনবার, দুটি অ্যাপে। প্রতিবার:
- পাবলিশটি লাইভ বলে চিহ্নিত হয়,
- কোনো রোলব্যাক চলেনি, কারণ কিছুই ব্যর্থ হয়নি,
- আমাদের রিকনসাইলার — একটি ব্যাকগ্রাউন্ড জব যা পরে ডেপ্লয়মেন্ট পরীক্ষা করে — কয়েক মিনিট পরে ডেপ্লয়মেন্টটিকে ব্যর্থ ঘোষণা করে,
- এবং পুরো সাইট 404 ফিরিয়ে দেয়।
যে পাবলিশ সময়মতো ব্যর্থ হয়, সেটি পুনরুদ্ধারযোগ্য: রোলব্যাক আগের সংস্করণ ফিরিয়ে আনে। যে পাবলিশ কয়েক মিনিট দেরিতে ব্যর্থ হয়, সফল ঘোষণা হওয়ার পর, সেটি ইতিমধ্যে তার রোলব্যাক এড়িয়ে গেছে।
আমরা কীভাবে ধরলাম
আমরা এটি স্থানীয়ভাবে পুনরুৎপাদন করি: একটি কাজ করা API নিই, সেটিকে ঘুমাতে দিই, তারপর একটি পরিবর্তনসহ পুনরায় পাবলিশ করি যা বুটে ক্র্যাশ করে। হেলথ চেক এটিকে লাইভ বলে চিহ্নিত করে।
এটি প্রোডাকশনের সঙ্গে মিলে গেল: তিনটি পাবলিশের প্রতিটিতে অ্যাপটি বুটের কয়েক সেকেন্ড পরে মারা যাচ্ছিল, অথচ চেকের তুলনা করা ক্র্যাশের সংখ্যা দুটি দেখার মাঝখানে বাড়ছিল না।
সমাধান: ক্র্যাশের সংখ্যা নয়, সর্বশেষ ক্র্যাশের তুলনা
ক্র্যাশ গোনার বদলে চেকটি এখন পাবলিশ শুরুর পর থেকে সর্বশেষ ক্র্যাশের সময় দেখে।
দ্বিতীয় দেখায় পাবলিশ শুরুর পর কোনো ক্র্যাশ থাকলে চেকটি অপেক্ষা করে তৃতীয়বার দেখে। যদি তৃতীয় দেখায় সর্বশেষ ক্র্যাশটি দ্বিতীয় দেখার সর্বশেষ ক্র্যাশের চেয়ে পরে হয়, তবে মাঝখানে মেশিনটি আবার ক্র্যাশ করেছে। সেটি স্থির থাকছে না, এবং পাবলিশটি এমন একটি বার্তাসহ ব্যর্থ হয় যে মেশিনটি পাবলিশের পর থেকে বারবার ক্র্যাশ করেছে এবং এখনও পুনরায় চালু হচ্ছে।
এটি ইভেন্ট তালিকা যত ছোটই হোক কাজ করে। পাঁচটি ইভেন্টের একটি সরে চলা উইন্ডো কতগুলো ক্র্যাশ ছিল তা লুকাতে পারে, কিন্তু নতুন একটি ক্র্যাশ ঘটেছে তা লুকাতে পারে না — সর্বশেষ ইভেন্টটিই সবসময় রাখা হয়।
এই পরিবর্তনের সঙ্গে স্থানীয় পুনরুৎপাদনটি সঠিকভাবে আচরণ করে: পাবলিশ ব্যর্থ হয়, এবং আগের ইমেজ ফিরে আসে। প্ল্যাটফর্মের আচরণের অনুকরণ করে এমন একটি টেস্টও আছে — প্রতিটি দেখায় একটি ক্র্যাশ ও একটি শুরু যোগ হয় এবং তালিকাটি পাঁচে ছাঁটা হয় — এবং সেটি যাচাই করে যে রায়টি পাস নয়, ব্যর্থতা।
আমরা যা শিখলাম
- আপনি যে ডেটা গুনছেন তার আকার জানুন। একটি সীমাবদ্ধ তালিকার উপর গণনা ভরাট হওয়ার পর আর কিছু বোঝায় না। সীমাটি লুকানো ছিল না; আমরা শুধু চেকটিকে সেটি মাথায় রেখে ডিজাইন করিনি।
- "কয়টি ঘটেছে?" এর চেয়ে "নতুন কিছু ঘটেছে কি?" ভালো প্রশ্ন। সর্বশেষ টাইমস্ট্যাম্প ছাঁটাইয়ের পরেও টিকে থাকে; মোট সংখ্যা টেকে না।
- দেরিতে ব্যর্থতা আগে ব্যর্থতার চেয়ে খারাপ। একই ভাঙা বিল্ড বিপজ্জনক নয় যদি পাবলিশ ব্যর্থ হয়ে রোলব্যাক করে; কিন্তু সেটি আগে সফল ঘোষিত হলে সাইট বন্ধ করে দেয়।
- আসল পরিস্থিতিতে পুনরুৎপাদন করুন। বাগটির জন্য এমন একটি মেশিন দরকার ছিল যেটি ইতিমধ্যে যথেষ্টবার ক্র্যাশ করে তার ইভেন্ট তালিকা ভরিয়ে ফেলেছে। একটি টেস্টে একটি দ্রুত ক্র্যাশ এটি দেখাত না।
এই সমাধানটি একই দিনের আরেকটি পরিবর্তনের সঙ্গে মিলে যায়, যা নিশ্চিত করেছে যে রোলব্যাক পুরনো সংস্করণটি ফিরিয়ে আনে, মুছে ফেলে না: একটি ব্যর্থ রিপাবলিশ কখনো কাজ করা ব্যাকএন্ড মোছে না। যদি আপনার নিজের অ্যাপ শুরুতেই ক্র্যাশ করার কারণে পাবলিশ ব্যর্থ হয়, তবে পাবলিশ ট্রাবলশুটিং ডক্স এবং AI-তে তৈরি অ্যাপ ডিবাগ করার গাইড শুরু করার ভালো জায়গা।