ایک پروڈکشن PostgreSQL ڈیپلائمنٹ کریش ہو گئی جب ایک ڈویلپر نے CREATE OR REPLACE FUNCTION کے ذریعے موجودہ فنکشن میں ایک اختیاری آرگیومنٹ (optional argument) شامل کیا۔ اس تبدیلی کی وجہ سے ایک ہی نام کے دو فنکشنز بن گئے، جس کے نتیجے میں ڈیٹا بیس نے “function is not unique” کا ایرر دیا اور API نے 400 ایرر جاری کیا۔ یہ واقعہ ظاہر کرتا ہے کہ کس طرح مائیگریشن کی ایک چھوٹی سی غلطی خاموشی سے لائیو اسکیمہ (live schema) کو خراب کر سکتی ہے اور کیوں صرف کوڈ لیول کے چیک کافی نہیں ہوتے۔
کیا غلط ہوا
ٹیم کو ایک اسٹورڈ پروسیجر (stored procedure) میں ایک اضافی، اختیاری پیرامیٹر شامل کرنے کی ضرورت تھی۔ انہوں نے یہ فرض کرتے ہوئے کہ یہ پرانی تعریف (definition) کو اوور رائٹ کر دے گا، CREATE OR REPLACE FUNCTION … چلایا۔ PostgreSQL فنکشن کو صرف اس وقت ریپلیس کرتا ہے جب آرگیومنٹ کی مکمل فہرست بالکل مماثل ہو۔ سگنیچر (signature) تبدیل کرنے سے ایک بالکل نیا فنکشن انٹری بن جاتا ہے جبکہ اصل فنکشن ویسا ہی رہتا ہے۔
چونکہ نئے آرگیومنٹ کی ایک ڈیفالٹ ویلیو تھی، اس لیے وہ کالرز (callers) جو پرانی تعداد میں آرگیومنٹ فراہم کرتے تھے، وہ دونوں تعریفوں سے میچ کر سکتے تھے۔ PostgreSQL فیصلہ نہیں کر سکا کہ کسے کال (invoke) کیا جائے اور "function is not unique" کا ایرر دے دیا، جو API کی جانب سے 400 رسپانس کے طور پر سامنے آیا۔
کوڈ ریپوزٹری میں صرف ایک تعریف نظر آ رہی تھی، اور ایک کسٹم اسکرپٹ جس نے سورس ٹری (source tree) کو اسکین کیا تھا، اس نے کسی بھی ڈپلیکیٹ کی اطلاع نہیں دی۔ یہ ڈپلیکیٹ صرف ڈیٹا بیس میں موجود تھا، جو اس وقت پیدا ہوا جب سرور پر ایک پرانی مائیگریشن فائل دوبارہ چلائی گئی۔
مائیگریشن کیوں نظر انداز ہو گئی
مائیگریشن جس نے اختیاری پیرامیٹر شامل کیا تھا، اس نے محض CREATE OR REPLACE FUNCTION چلایا تھا۔ جب مائیگریشن دوسری بار چلی—شاید رول بیک (rollback) کے بعد یا دوبارہ ڈیپلائمنٹ کے دوران—تو ڈیٹا بیس نے اس کمانڈ کو "موجودہ کو ریپلیس کرنے" کے بجائے "ایک نیا اوور لوڈ (overload) شامل کرنے" کے طور پر لیا۔ مائیگریشن نے نتیجے کی حالت (resulting state) کی تصدیق نہیں کی، اس لیے ڈپلیکیٹ نظر آئے بغیر برقرار رہا۔
ریپوزٹری کو چیک کرنے والے اسکرپٹ نے سورس فائلوں کا معائنہ کیا، لائیو اسکیمہ کا نہیں۔ وہ سامنے کا دروازہ دیکھ رہا تھا جبکہ بگ (bug) پیچھے کے راستے سے داخل ہوا۔
خطرات
ایک بھی مبہم فنکشن (ambiguous function) کسی بھی ایسی سروس کو مفلوج کر سکتا ہے جو اس پر انحصار کرتی ہے۔ اس کا حل یہ تھا کہ اگر فنکشن کی تعداد غلط ہو تو ٹرانزیکشن کو رول بیک کیا جائے اور اسکیمہ کیش (schema cache) کو دوبارہ لوڈ کرنے کے لیے مطلع کیا جائے۔
مائیگریشن کو کیسے محفوظ بنایا جائے
ٹیم نے مائیگریشن کو واضح چیکس کے ساتھ دوبارہ ترتیب دیا، جس سے یہ ایک خودکار تصدیقی عمل (self-asserting operation) بن گیا:
- ایک ٹرانزیکشن شروع کریں تاکہ کسی بھی ناکامی کی صورت میں پوری تبدیلی رول بیک ہو جائے۔
- پرانے فنکشن کو واضح طور پر ڈراپ کریں نیا ورژن بنانے سے پہلے، تاکہ اس بات کی ضمانت ہو سکے کہ صرف ایک ہی تعریف موجود ہے۔
- نیا فنکشن بنائیں مطلوبہ سگنیچر کے ساتھ۔
pg_catalogمیں دیے گئے نام کے ساتھ فنکشنز کی تعداد گنیں اور تصدیق کریں کہ تعداد بالکل ایک ہے۔- اگر تعداد میں فرق ہو تو ٹرانزیکشن کو رول بیک کریں، تاکہ ڈپلیکیٹ برقرار نہ رہے۔
- اسکیمہ کیش کو مطلع کریں تاکہ وہ دوبارہ لوڈ ہو جائے، اور اس بات کو یقینی بنایا جا سکے کہ بعد میں آنے والی کوئریز اپ ڈیٹ شدہ تعریف دیکھ سکیں۔
کوڈ کے درست ہونے کا فرض کر لینے کے بجائے ڈیٹا بیس سے یہ پوچھ کر کہ "کون سے فنکشنز موجود ہیں؟"، مائیگریشن بار بار چلانے، جزوی ڈیپلائمنٹ، یا دستی تبدیلیوں کے خلاف قابل اعتماد بن جاتی ہے۔
مخالف دلیل: سہولت بمقابلہ حفاظت
CREATE OR REPLACE FUNCTION اس لیے پرکشش ہے کیونکہ یہ ڈویلپرز کو الگ سے ڈراپ اسٹیٹمنٹس لکھے بغیر تیزی سے کام کرنے (iterate) کی اجازت دیتا ہے۔ ایسے ماحول میں جہاں مائیگریشن صرف ایک بار چلتی ہے اور دوبارہ کبھی نہیں چلتی، یہ شارٹ کٹ ٹھیک کام کرتا ہے۔ خطرہ اس وقت پیدا ہوتا ہے جب مائیگریشن کو دوبارہ چلایا جائے—خواہ وہ ٹیسٹ ڈیٹا بیس کو ری سیٹ کرنے والی CI پائپ لائنز کی وجہ سے ہو، خودکار رول بیک کی وجہ سے ہو، یا پروڈکشن میں دستی طور پر دوبارہ لاگو کرنے کی وجہ سے ہو۔
خلاصہ
CREATE OR REPLACE کے ساتھ فنکشن کے سگنیچر کو تبدیل کرنے سے ریپلیسمنٹ کی ضمانت نہیں ملتی—اگر آرگیومنٹ کی فہرست مختلف ہو تو PostgreSQL خاموشی سے ایک اوور لوڈ بنا دے گا۔ وہ پروڈکشن ماحول جو مائیگریشن پر انحصار کرتے ہیں، انہیں صرف سورس کوڈ ہی نہیں بلکہ نتیجے کے اسکیمہ کی بھی تصدیق کرنی چاہیے۔ واضح ڈراپس، ٹرانزیکشنل چیکس، اور مائیگریشن کے بعد کے اثبات (assertions) شامل کرنے سے ایک آسان شارٹ کٹ ایک قابل اعتماد اور قابلِ تکرار عمل میں بدل جاتا ہے۔
