Laravel 13.31 ইন্টারাপ্টেবল জবস (interruptible jobs) যুক্ত করেছে, যা কিউ ওয়ার্কারদের (queue workers) ডিপ্লয়মেন্টের সময় পাঠানো SIGTERM সিগন্যাল ধরতে এবং কোনো কাজ মাঝপথে বাতিল করার পরিবর্তে পরিচ্ছন্নভাবে শাট ডাউন করতে সাহায্য করে। যেসব টিম দীর্ঘ সময় ধরে চলা কাজ পরিচালনা করে—যেমন হাজার হাজার রো প্রসেস করা, বাল্ক ইমেল পাঠানো বা রিপোর্ট তৈরি করা—তারা এর সুবিধা পাবে কারণ নতুন রিলিজ চালু হওয়ার সময় ডেটা কনসিস্টেন্ট বা সামঞ্জস্যপূর্ণ থাকবে।
কেন ডিপ্লয়মেন্ট জবগুলোকে নষ্ট করে দিচ্ছিল
যখন একটি নতুন ভার্সন আসে, তখন Supervisor, Docker এবং Kubernetes-এর মতো প্রসেস ম্যানেজারগুলো বিদ্যমান ওয়ার্কারদের বন্ধ করার জন্য SIGTERM পাঠায়, যা মূলত বন্ধ করার একটি ভদ্র অনুরোধ। বেশিরভাগ ওয়ার্কার প্রসেস বন্ধ করার আগে বর্তমান জবটি শেষ হওয়ার জন্য অপেক্ষা করে। সমস্যাটি তখন দেখা দেয় যখন ম্যানেজার এই অনুরোধ মেনে চলার জন্য মাত্র কয়েক সেকেন্ড সময় দেয়। যদি একটি জবের জন্য কয়েক মিনিট প্রয়োজন হয়, তবে ম্যানেজার SIGKILL পাঠিয়ে প্রসেসটিকে তাৎক্ষণিকভাবে বন্ধ করে দেয়। এর ফলে জবটি কখনোই একটি কনসিস্টেন্ট অবস্থায় পৌঁছাতে পারে না, যা আংশিক আপডেট করা রেকর্ড, অরফানিড ফাইল বা ডুপ্লিকেট কাজের সৃষ্টি করে।
Laravel-এর সমাধান: কোঅপারেটিভ ইন্টারাপশন
Laravel 13.31 Interruptible নামক একটি কন্ট্রাক্ট প্রবর্তন করেছে যা একটি জব ক্লাস ইমপ্লিমেন্ট করতে পারে যাতে সেটি টার্মিনেশন রিকোয়েস্ট সম্পর্কে সচেতন হতে পারে। যখন SIGTERM আসে, Laravel জবের interrupted() মেথডটি কল করে। ফ্রেমওয়ার্কটি স্বয়ংক্রিয়ভাবে জবটি বন্ধ করে দেয় না; জবটিকে অবশ্যই Laravel সেট করা একটি ফ্ল্যাগ চেক করতে হবে এবং নিজে থেকে বেরিয়ে যেতে হবে। এই কোঅপারেটিভ মডেলটি ডেভেলপারদের বর্তমান লুপ ইটারেশন শেষ করতে, আংশিক পরিবর্তনগুলো রোল ব্যাক করতে বা প্রস্থান করার আগে একটি চেকপয়েন্ট লিখতে সাহায্য করে।
কীভাবে একটি জবকে ইন্টারাপ্টেবল করবেন
- কন্ট্রাক্টটি ইমপ্লিমেন্ট করুন – জব ক্লাস ডেফিনিশনে
implements Interruptibleযোগ করুন। - ওয়ার্ক লুপের ভেতরে ফ্ল্যাগটি চেক করুন – প্রতিটি ইটারেশনে একটি চেক ইনসার্ট করুন যাতে দেখা যায় জবটি বন্ধ হওয়া উচিত কি না।
- ক্লিনআপ সম্পন্ন করুন –
interrupted()মেথডে, এমন কোনো স্টেট সংরক্ষণ করুন যা জবটিকে পরে পুনরায় শুরু করতে সাহায্য করবে, অথবা পরবর্তী বিশ্লেষণের জন্য ইন্টারাপশনটি লগ করুন।
সবচেয়ে বড় ফাঁদ: --once ব্যবহার করবেন না
php artisan queue:work --once দিয়ে কিউ ওয়ার্কার চালালে সিগন্যাল হ্যান্ডলিং পুরোপুরি নিষ্ক্রিয় হয়ে যায়। ওয়ার্কারটি একটি মাত্র জব প্রসেস করে এবং বেরিয়ে যায়, কিন্তু এটি কখনোই SIGTERM হ্যান্ডলারটি রেজিস্টার করে না। ফলে, যেকোনো ইন্টারাপ্টেবল জব টার্মিনেশন রিকোয়েস্ট উপেক্ষা করে এবং প্রসেস চলাকালীন মাঝপথে বন্ধ হয়ে যায়। এই প্যাটার্নটি ক্রন-চালিত (cron-driven) কন্টেইনার এবং ওয়ান-শট ডিপ্লয়মেন্টে দেখা যায়। যখনই আপনার ইন্টারাপ্টেবল জবের প্রয়োজন হবে, তখন ডেমোন মোড (php artisan queue:work) চালিয়ে এটি সমাধান করুন।
ইন্টারাপশন পর্যবেক্ষণ করা
Laravel দুটি ইভেন্ট ফায়ার করে যা আপনি হুক (hook) করতে পারেন:
- WorkerInterrupted – যখনই কোনো ওয়ার্কার SIGTERM পায় তখনই এটি নির্গত হয়। এই ইভেন্টটি লগ করলে ডিপ্লয়মেন্ট কত ঘন ঘন ওয়ার্কারদের বাধা দিচ্ছে তার একটি উচ্চ-স্তরের ধারণা পাওয়া যায়।
- JobInterrupted – এটি কেবল তখনই নির্গত হয় যদি বর্তমান জবটি Interruptible কন্ট্রাক্টটি ইমপ্লিমেন্ট করে। টেম্পোরারি ফাইল মুছে ফেলা বা “last processed row” মার্কার আপডেট করার মতো জব-নির্দিষ্ট ক্লিনআপ ট্রিগার করতে এই ইভেন্টটি ব্যবহার করুন।
এই ইভেন্টগুলো শোনার মাধ্যমে টিমগুলো এমন ড্যাশবোর্ড তৈরি করতে পারে যা ডিপ্লয়মেন্টের প্রভাব দেখায় এবং যে জবগুলো ঘন ঘন মাঝপথে থেমে যাচ্ছে তা শনাক্ত করতে পারে।
কিউ সাইজ রিপোর্টিংয়ে পরিবর্তন
এই রিলিজটি কিউ ম্যানেজারে একটি totalSize() মেথড যুক্ত করেছে, যা সমস্ত কিউ জুড়ে পেন্ডিং জবের মোট সংখ্যা রিটার্ন করে। ডাটাবেস-ব্যাকড এবং Redis ড্রাইভারের জন্য এই মানটি নির্ভরযোগ্য, কারণ তারা প্রকৃত সংখ্যা রিপোর্ট করে। SQS, Sync এবং Beanstalkd-এর মতো ড্রাইভারগুলো এখনও শূন্য রিটার্ন করে কারণ তারা Laravel-এর API-এর মাধ্যমে কোনো কাউন্ট প্রকাশ করে না। যারা SQS ব্যবহার করছেন, তাদের কিউ ডেপথের জন্য CloudWatch মেট্রিক্সের ওপর নির্ভর করা চালিয়ে যাওয়া উচিত।
বিভিন্ন সেটআপের জন্য এর অর্থ কী
- Docker/Kubernetes – গ্রেসফুল শাটডাউন পিরিয়ড এখন কার্যকরভাবে ব্যবহার করা যেতে পারে। টার্মিনেশন গ্রেস পিরিয়ড বাড়িয়ে দিন যাতে জবগুলো ফ্ল্যাগটি লক্ষ্য করার এবং পরিচ্ছন্নভাবে বেরিয়ে যাওয়ার জন্য কয়েক সেকেন্ড সময় পায়।
- Supervisor – ইন্টারাপশন ফ্ল্যাগ পাওয়ার পর একটি জব শেষ করতে আপনার যতটুকু সময় মনে হয়, তার চেয়ে বেশি
stopwaitsecsসেট করুন। - Legacy jobs – যে কোনো জব যা ম্যানেজারের টাইমআউটের চেয়ে বেশি সময় ধরে চলে তা পর্যালোচনা করুন এবং যেখানে সম্ভব সেটিকে ইন্টারাপ্টেবল করে তুলুন।
পাল্টা যুক্তি: অতিরিক্ত জটিলতা
এই ফিচারটি সঠিক টাইমআউট কনফিগারেশনের বিকল্প নয়। যদি কোনো জবের লুপ কখনোই ইন্টারাপশন ফ্ল্যাগ চেক না করে, তবে ম্যানেজার তবুও SIGKILL পাঠাবে। টিমগুলোকে দীর্ঘ সময় ধরে চলা কোড পাথগুলো অডিট করতে হবে এবং লজিক্যাল ব্রেকপয়েন্টগুলোতে চেক ইনসার্ট করতে হবে। কিছু ডেভেলপার ছোট জবের জন্য—যা ইতিমধ্যে শাটডাউন উইন্ডোর মধ্যে শেষ হয়ে যায়—অতিরিক্ত বয়লারপ্লেট (একটি কন্ট্রাক্ট ইমপ্লিমেন্ট করা এবং ফ্ল্যাগ চেক যোগ করা) অপছন্দ করতে পারেন।
অ্যাকশন চেকলিস্ট
- ডিপ্লয়মেন্ট স্ক্রিপ্টগুলোতে
--onceফ্ল্যাগটি খুঁজুন এবং যেখানে ইন্টারাপ্টেবল (interruptible) জব ব্যবহার করা হয় সেখানে এটি ডেমোন মোড (daemon mode) দিয়ে প্রতিস্থাপন করুন। - সবচেয়ে দীর্ঘ সময় ধরে চলা জবগুলো (যেগুলো হাজার হাজার রো বা সারি নিয়ে কাজ করে অথবা কয়েক মিনিট ধরে চলে) শনাক্ত করুন এবং সেখানে
Interruptibleকন্ট্রাক্ট যুক্ত করুন। - প্রতিটি লুপ ইটারেশনের ভেতরে একটি ফ্ল্যাগ চেক যুক্ত করুন এবং প্রয়োজনীয় যেকোনো ফাইনলাইজেশন কোড
interrupted()মেথডে সরিয়ে নিন। - ডিপ্লয়মেন্ট কত ঘন ঘন প্রসেসিংকে প্রভাবিত করে তার মেট্রিক্স সংগ্রহ করতে
WorkerInterruptedএবংJobInterrupted-এ লিসেনার হুক করুন। - Redis বা ডাটাবেস কিউ-এর ক্ষেত্রে ব্যাকলগ মনিটর করতে
totalSize()ব্যবহার করুন; SQS-এর জন্য CloudWatch অ্যালার্ম চালু রাখুন।
ডিপ্লয়মেন্ট-চালিত শাটডাউনগুলোকে আকস্মিক বন্ধ (abrupt kill) হিসেবে না দেখে একটি সমন্বিত পদক্ষেপ হিসেবে বিবেচনা করুন। Laravel 13.31 ডেটার সামঞ্জস্য বজায় রাখে এবং অর্ধেক সম্পন্ন হওয়া জবগুলোর অপারেশনাল জটিলতা কমিয়ে দেয়। এর বিনিময়ে কোডের দায়িত্ব কিছুটা বৃদ্ধি পায়, তবে যে দলগুলো ভারী ব্যাকগ্রাউন্ড প্রসেসিংয়ের ওপর নির্ভর করে, তারা একটি আরও নির্ভরযোগ্য প্রোডাকশন এনভায়রনমেন্ট পায়।
