Elevare Digital-এর আপনার AI এজেন্টটি নিষ্ক্রিয় (idle) হয়ে গিয়েছিল কারণ একটি নতুন যোগ করা PostgreSQL row-level security (RLS) পলিসি প্রতিটি জব রো (job row) ফিল্টার করে দিয়েছিল, যার ফলে কিউ (queue) খালি বলে মনে হচ্ছিল। ভুলটি ধরা পড়েনি যতক্ষণ না কাজগুলো স্তূপাকার হয়ে গেল, যা টিমকে অর্কেস্ট্রেটর (orchestrator) কীভাবে একটি খালি কিউ শনাক্ত করে তা পুনরায় ডিজাইন করতে বাধ্য করেছিল।
লুকানো অন্ধবিন্দু
ARIA, Elevare-এর একটি স্বায়ত্তশাসিত AI সিস্টেম, পেন্ডিং কাজের জন্য একটি PostgreSQL টেবিল পোল (poll) করে। কুয়েরিটি সফল হয়েছিল, শূন্যটি রো (row) রিটার্ন করেছিল এবং এজেন্টটি নিষ্ক্রিয় হয়ে পড়েছিল। বাস্তবে টেবিলটি পূর্ণ ছিল। একটি RLS পলিসি SELECT অ্যাক্সেসকে নির্দিষ্ট কিছু ব্যবহারকারীর মধ্যে সীমাবদ্ধ করে দিয়েছিল। অর্কেস্ট্রেটর এমন একটি সার্ভিস রোলের (service role) মাধ্যমে সংযুক্ত হয়েছিল যার 'bypass privilege' ছিল না, তাই ডাটাবেস নীরবে রেজাল্ট সেট থেকে প্রতিটি রো সরিয়ে ফেলেছিল। PostgreSQL একটি ফিল্টার করা রিডকে (read) একটি খালি টেবিলের মতোই বিবেচনা করে, তাই কোনো এরর (error), ওয়ার্নিং (warning) বা ফেইলর কোড (failure code) দেখা দেয়নি। নিষ্ক্রিয় এজেন্টের একটি স্বাভাবিক হার্টবিট (heartbeat) থেকে কোনো ইঙ্গিত পাওয়া যায়নি যে কিছু ভুল হয়েছে।
কীভাবে RLS একটি পূর্ণ কিউকে নিস্তব্ধতায় পরিণত করল
RLS একটি SELECT করার সময় প্রতিটি রো-তে একটি প্রেডিকেট (predicate) যোগ করে। যদি প্রেডিকেটটি মিথ্যা (false) হয়, তবে রো-টি রেজাল্ট থেকে অদৃশ্য হয়ে যায়। ক্লায়েন্ট কেবল সেই রো-গুলোই দেখতে পায় যা পলিসি পূরণ করে; রো-গুলো যে লুকানো ছিল তা সে কখনোই জানতে পারে না। একটি কিউ ওয়ার্কারের (queue worker) জন্য, একটি খালি রেজাল্ট সেট দেখতে হুবহু একটি প্রকৃত খালি কিউয়ের মতোই মনে হয়। অর্কেস্ট্রেটর ধরে নিয়েছিল “কোনো রো নেই = কোনো কাজ নেই” এবং এর ফলে কাজগুলো পর্দার আড়ালে জমা হতে থাকল যখন এটি তার আইডল লুপে (idle loop) প্রবেশ করল।
টিমটি আবিষ্কার করল যে, রিডগুলোকে ব্যক্তিগত ব্যবহারকারীদের মধ্যে সীমাবদ্ধ করার জন্য তৈরি করা একটি পলিসি অনিচ্ছাকৃতভাবে সার্ভিস রোলটিকেও অন্তর্ভুক্ত করে ফেলেছিল। যেহেতু সেই রোলের বিশেষ “bypass RLS” অ্যাট্রিবিউট ছিল না, তাই অর্কেস্ট্রেটর যে কুয়েরিগুলো পাঠাচ্ছিল তার সবগুলোতে পলিসিটি প্রয়োগ হচ্ছিল। এটি সিকিউরিটি বনাম অবজারভেবিলিটির (security-vs-observability) একটি ক্লাসিক ট্রেড-অফকে চিত্রিত করে: RLS অননুমোদিত ব্যবহারকারীদের থেকে ডেটা রক্ষা করে, কিন্তু এটি সিস্টেমের সেই অংশগুলোর জন্য একটি দরকারী ফেইলর সিগন্যালকেও (failure signal) সরিয়ে দেয় যা ভিজিবিলিটির ওপর নির্ভর করে।
ক্যানারি-চেক প্যাটার্ন
একটি নিঃশব্দ খালি রেজাল্টের ওপর নির্ভরতা কমাতে, Elevare একটি “ক্যানারি” (canary) চেক যোগ করেছে। নতুন ফ্লো (flow) হলো:
- পেন্ডিং-জবস (pending-jobs) টেবিলটি কুয়েরি করুন।
- যদি রো রিটার্ন করা হয়, তবে আগের মতোই সেগুলো প্রসেস করুন।
- যদি রেজাল্ট খালি হয়, তবে একটি ডেডিকেটেড ক্যানারি রো-এর বিপরীতে দ্বিতীয় একটি কুয়েরি চালান যা সর্বদা বিদ্যমান থাকতে হবে।
- যদি ক্যানারি কুয়েরি প্রত্যাশিত রো রিটার্ন করে, তবে কিউটি সত্যিই খালি; একটি আইডল হার্টবিট (idle heartbeat) লগ করুন।
- যদি ক্যানারি কুয়েরিও কিছু রিটার্ন না করে, তবে এজেন্টটি অন্ধ (blind); অবিলম্বে একটি অ্যালার্ট (alert) দিন।
এখন অর্কেস্ট্রেটর তিনটি অবস্থার মধ্যে পার্থক্য করতে পারে:
- জব পাওয়া গেছে – স্বাভাবিক প্রসেসিং।
- কোনো জব নেই, ক্যানারি ঠিক আছে – প্রকৃত আইডল পিরিয়ড।
- কোনো জব নেই, ক্যানারি ব্যর্থ হয়েছে – লুকানো RLS ব্লক, অ্যালার্ট ট্রিগার করুন।
ক্যানারি টেবিলটি একটি সিঙ্গেল রো যা কখনোই পরিবর্তিত হয় না। এটি সেট আপ করতে প্রায় এক ঘণ্টা সময় লেগেছিল, কিন্তু এটি নিঃশব্দ ফেইলর বা ব্যর্থতার একটি সম্পূর্ণ শ্রেণীকে নির্মূল করে দেয়।
টিমের যা করা উচিত
আপনি যদি PostgreSQL বা এর ওপর ভিত্তি করে তৈরি কোনো হোস্ট করা সার্ভিসের (যেমন Supabase) বিপরীতে কিউ ওয়ার্কার চালান, তবে এই পদক্ষেপগুলো অনুসরণ করুন:
- “bypass RLS” ফ্ল্যাগসহ একটি service-role credential ব্যবহার করুন। এটি ইউজার-লেভেল পলিসি নির্বিশেষে সিস্টেমের উপাদানগুলোকে সমস্ত রো দেখতে সাহায্য করে।
- সার্ভিস রোলগুলোর জন্য মিসিং বাইপাস পারমিশন আছে কিনা তা পরীক্ষা করতে RLS পলিসিগুলো অডিট করুন। এন্ড-ইউজারদের জন্য একটি পলিসি সঠিক মনে হলেও তা অনিচ্ছাকৃতভাবে অভ্যন্তরীণ সার্ভিসগুলোকে আটকে ফেলতে পারে।
- একটি ক্যানারি টেবিল (বা সমতুল্য সর্বদা বিদ্যমান কোনো রো) যোগ করুন এবং ওয়ার্কারের আইডল লজিকের মধ্যে ক্যানারি চেক অন্তর্ভুক্ত করুন। অতিরিক্ত কুয়েরিটি খুব সামান্য খরচ সাপেক্ষ এবং এটি একটি স্পষ্ট সেফটি নেট (safety net) প্রদান করে।
ট্রেড-অফ
সূক্ষ্ম ডেটা অ্যাক্সেস (fine-grained data access) প্রয়োগ করার জন্য RLS একটি শক্তিশালী টুল হিসেবে রয়ে গেছে। এটি কোডবেসের সর্বত্র অ্যাপ্লিকেশন-লেভেল ফিল্টার ছড়িয়ে না দিয়ে দুর্ঘটনাবশত ডেটা লিক প্রতিরোধ করে এবং মাল্টি-টেন্যান্ট আর্কিটেকচারকে সমর্থন করে। এর অসুবিধা হলো, এটি এমন উপাদানগুলোর কাছ থেকে ব্যর্থতা লুকিয়ে রাখতে পারে যারা একটি সাধারণ “কোনো রো নেই” সিগন্যালকে “করার কিছু নেই” হিসেবে ধরে নেয়। ক্যানারি প্যাটার্ন RLS-কে দুর্বল করে না; এটি একটি হালকা যাচাইকরণ ধাপ যোগ করে যা অবজারভেবিলিটি (observability) পুনরুদ্ধার করে।
মূল কথা
একটি লুকানো RLS পলিসি একটি ব্যস্ত কিউকে নিঃশব্দ ডেড এন্ডে (dead end) পরিণত করতে পারে, যার ফলে কাজ জমে থাকা সত্ত্বেও AI এজেন্টগুলো নিষ্ক্রিয় থেকে যায়। সার্ভিস রোলগুলোকে সঠিক বাইপাস প্রিভিলেজ প্রদান করুন এবং প্রতিটি খালি-কিউ রিডকে একটি ক্যানারি চেকের সাথে যুক্ত করুন; এতে টিমগুলো তাদের স্বায়ত্তশাসিত ওয়ার্কারগুলোকে সঠিকভাবে পরিচালনা করতে পারবে এবং ব্যয়বহুল অন্ধবিন্দু এড়াতে পারবে।
