فون سوئے تو چیٹ کو زندہ رکھنا
Mythex کا ایجنٹ ایک درخواست پر منٹوں تک کام کر سکتا ہے، اور آپ شاید فون سے دیکھ رہے ہوں، جو کام کے دوران لاک ہوتا ہے، ایپس بدلتا ہے اور نیٹ ورک بدلتا ہے۔ دو bugs نے اس کو خراب کیا۔ ایک میں چیٹ ہر “صفحہ دوبارہ نظر آیا” والے سگنل کو اس بات کا ثبوت سمجھتی تھی کہ اس کا کنکشن مر چکا ہے، اور “Connecting…” پر لوپ ہو جاتی تھی۔ دوسرے میں ایک فون جو نئی چیٹ کا پہلا جواب سوتے ہوئے گزار گیا، واپس آیا تو اسے جواب کے صرف چند ابتدائی ٹکڑے ملے، جب تک کہ دستی طور پر refresh نہ کیا جائے۔ دونوں ٹھیک ہو چکے ہیں۔
چیٹ چلتے turn کو کیسے فالو کرتی ہے
ایجنٹ کام کرتا رہتا ہے تو چیٹ ہمارے سرورز سے ایک stream کھلا رکھتی ہے: ہر قدم، یعنی ایک سوچ، ایک tool call، یا جواب کا ایک ٹکڑا، ایک event کے طور پر آتا ہے۔ اگر stream ٹوٹ جائے تو چیٹ دوبارہ کنیکٹ کرتی ہے، اور سرور حالیہ events ایک buffer سے دوبارہ چلاتا ہے، جو آخری 120 سیکنڈ رکھتا ہے۔ turn ختم ہونے پر چیٹ سرور سے محفوظ تاریخ بھی مانگتی ہے، اور جو وہ دکھا چکی ہے اسے اس سے ملاتی ہے۔ یہ آخری قدم وہ چیز پکڑتا ہے جو stream سے چھوٹ گئی ہو۔
جب کچھ نہ ہو رہا ہو تو زندہ اور مردہ کنکشن میں فرق کرنے کے لیے سرور ہر 15 سیکنڈ پر ایک چھوٹا “ping” بھیجتا ہے۔
Bug 1: جاگنے سے ایک صحت مند stream ختم ہو جاتا تھا
Browsers صفحے کو بتاتے ہیں کہ وہ دوبارہ نظر آنے لگا ہے: tab بدلنے کے بعد، اسکرین کھلنے کے بعد۔ ہم اسے کنکشن جانچنے کے اشارے کے طور پر استعمال کرتے تھے، اور عملی طور پر stream کو abort کر کے دوبارہ کنیکٹ کر دیتے تھے، یہ فرض کرتے ہوئے کہ وہ چھپے ہونے کے دوران مر گیا۔
فونز اور embedded browsers پر یہ events اس سے کہیں زیادہ آتے ہیں جتنی بار streams واقعی مرتے ہیں: ہر tab بدلنے پر، ہر unlock پر، اور کچھ embedded browsers میں ہر چند سیکنڈ بعد۔ ہر ایک صحت مند stream کو abort کر دیتا تھا۔ چیٹ دوبارہ کنیکٹ ہوتی، دوبارہ چلاتی، پھر دوبارہ abort ہو جاتی، اور آخر میں “Connecting…” پر اٹک جاتی۔ پھر وہ کہتی کہ turn ختم ہو گیا ہے، حالانکہ ایجنٹ ابھی بھی کام کر رہا تھا۔
حل: stream کو اس سے جانچیں کہ وہ بول رہا ہے یا نہیں
چیٹ اب ریکارڈ کرتی ہے کہ ہر پروجیکٹ کے stream کو آخری بار کچھ بھی کب ملا تھا، events اور 15 سیکنڈ کے pings دونوں۔ “دوبارہ نظر آیا” کا سگنل صرف اس stream کو abort کرتا ہے جو 25 سیکنڈ سے خاموش ہو: یہ ping کے وقفے اور ایک سست نیٹ ورک hop کے مجموعے سے زیادہ ہے، اس لیے زندہ stream کبھی اس شرط میں نہیں آتا۔ ٹیسٹ جانچتے ہیں کہ ping زندگی کی نشانی کے طور پر شمار ہوتا ہے، اور جو stream ابھی ping کر چکا ہو اسے مردہ نہیں سمجھا جاتا۔
اس سے ہم نے یہ اصول لیا: صفحے کا نظر آنا صفحے کے بارے میں بتاتا ہے، نیٹ ورک کنکشن کے بارے میں نہیں۔ کنکشن سے پوچھیں۔
Bug 2: فون جاگنے کے بعد آدھا جواب
یہ ہم ہر بار iOS simulator میں دوبارہ پیدا کر سکتے تھے:
- ایک نئی چیٹ شروع کریں اور ایک ایسی درخواست بھیجیں جس میں کچھ وقت لگے۔
- build کے دوران فون کو سونے دیں۔
- turn ختم ہونے اور دو منٹ کا replay buffer ختم ہونے کے بعد واپس آئیں۔
چیٹ جواب کے ابتدائی چند بلاک دکھاتی تھی، انہیں مکمل نشان زد کر کے، اور صفحہ refresh کرنے تک یہی رہتا تھا۔
کیوں
نئی چیٹ میں پہلا پیغام بننے تک کوئی thread، یعنی محفوظ شدہ گفتگو، نہیں ہوتی۔ thread پہلا پیغام بھیجنے والے function کے اندر بنتا ہے، اور یہ اس سے بعد ہوتا ہے جب send اپنی reconcile مرحلہ پہلے ہی پکڑ چکا تھا، جو ابھی بھی سمجھتا تھا کہ کوئی thread نہیں ہے۔ اس لیے پہلے turn کے اختتام پر reconcile نے کوئی thread نہ دیکھا اور بغیر کچھ مانگے خاموشی سے لوٹ گیا۔
عام طور پر کسی کو پتا نہیں چلتا تھا، کیونکہ stream نے پورا turn پہنچا ہی دیا ہوتا تھا۔ مگر ایک فون جو turn کے دوران سوتا رہا اور 120 سیکنڈ کا replay buffer ختم ہونے کے بعد واپس آیا، وہ stream سے غائب events نہیں لے سکتا تھا، اور وہ reconcile جو خالی جگہ بھرتا، کبھی چلا ہی نہیں تھا۔
حل
- Send reconcile کو بتاتا ہے کہ turn کس thread کا ہے، اس لیے نئی چیٹ کے پہلے turn کو بھی باقی ہر turn کی طرح reconcile کیا جاتا ہے۔ اگر جواب واپس آنے تک آپ کسی اور چیٹ پر جا چکے ہوں تو نتیجہ غلط جگہ دکھانے کے بجائے چھوڑ دیا جاتا ہے۔
- ناکام reconcile دوبارہ کوشش کیا جاتا ہے۔ خراب کنکشن پر جاگنے والا فون دیکھ سکتا ہے کہ turn ختم ہو چکا ہے، اور پھر اسے لانے میں ناکام ہو جاتا ہے۔ یہ اب یاد رکھا جاتا ہے، اور جب tab دوبارہ دکھایا جائے یا نیٹ ورک واپس آئے تو چیٹ دوبارہ پوچھتی ہے۔
- “Worked for” سچا ہے۔ ہر جواب دکھاتا ہے کہ ایجنٹ کتنی دیر کام کرتا رہا۔ اگر tab نے سرور کا turn ختم ہونے کا پیغام کبھی نہ دیکھا ہو تو وہ پہلے اپنی گھڑی سے یہ قیمت بھر دیتا تھا، جو Send سے لے کر فون جاگنے تک چلتی تھی، جس میں دور رہنے کا وقت بھی شامل ہوتا تھا۔ اب یہ عدد اندازہ کے طور پر نشان زد ہوتا ہے، اور تاریخ آنے پر محفوظ شدہ دورانیے سے بدل جاتا ہے۔
ہم نے کیا سیکھا
- اصل صارفین کے آلے پر، جس طرح وہ استعمال کرتے ہیں، جانچیں۔ دونوں bugs “ایک کام کرنے والا stream” اور “جیب میں پڑا فون” کے درمیان خلا میں رہتے تھے۔
- جو fallback کبھی نہ چلے وہ fallback نہیں ہوتا۔ reconcile مرحلہ اسی حالت کو پکڑنے کے لیے تھا، اور وہ خاموشی سے اسے چھوڑ دیتا تھا۔
- بحالی کو بھی دوبارہ کوشش کرنے دیں۔ جس لمحے فون جاگتا ہے اکثر اسی وقت اس کا کنکشن سب سے کمزور ہوتا ہے۔
- اندازے کو حقیقت کے طور پر نہ دکھائیں۔ غلط گھڑی سے نکالا گیا دورانیہ کسی بھی دورانیے سے بدتر ہے؛ اسے نشان زد کریں یا بدل دیں۔
اسی کام میں کچھ اور چیزیں بھی سنواری گئیں جو turn چلتے وقت نظر آتی ہیں: shell کے مراحل اب cd کے بجائے اس کمانڈ کے نام سے لیبل ہوتے ہیں جو اصل کام کرتی ہے، چیٹ کی screenshots صفحے کا اوپر بایاں حصہ رکھتی ہیں اور کالم میں فٹ ہوتی ہیں، اور نیا پروجیکٹ بغیر refresh کے اپنا بنایا ہوا نام لے لیتا ہے۔
اگر آپ فونز کے لیے اپنی app بنا رہے ہیں تو ہماری گائیڈز موبائل دوست ویب ایپ کیسے بنائیں اور native بمقابلہ progressive web apps بنیادی باتیں کور کرتی ہیں۔ خود چیٹ کے بارے میں مزید chat docs میں ہے۔