ترحيل ناجح إلى حل XMPP مخصص

نشرت: 2019-04-08

سوف أتحدث إليكم عن التحديات التي واجهناها في الترحيل من محادثة طرف ثالث إلى حل رسائل مخصص قائم على XMPP لعملائنا ، Forward Health ، وهو حل للرعاية الصحية للمراسلة مقره المملكة المتحدة. ستغطي هذه المقالة أسباب الهجرة ، وتوقعاتنا مقابل حقائق التنفيذ ، والتحدي المتمثل في بناء وظائف إضافية.

من أين بدأنا

أراد عميلنا ، Forward Health ، إنشاء تطبيق اتصالات محمول للعاملين في مجال الرعاية الصحية في المملكة المتحدة ، بما في ذلك وظائف الدردشة. كشركة ناشئة ، أرادوا عرض منتجهم العملي بسرعة. في الوقت نفسه ، يجب أن تكون الرسائل موثوقة وقوية وقادرة على إرسال بيانات المريض الحساسة بشكل آمن. لتحقيق ذلك ، قررنا استخدام أحد حلول الجهات الخارجية المتاحة لوظيفة الدردشة .

وظيفة الدردشة ليست بالأمر التافه ، خاصة عندما تهدف إلى دعم صناعة الرعاية الصحية. مع نمو التطبيق ، واجهنا المزيد من حالات الحافة وبعض الأخطاء على جانب المكتبة التي لم تكن الجهة الخارجية راغبة في العمل عليها. بالإضافة إلى ذلك ، أراد Forward Health إضافة ميزات جديدة لم تكن مدعومة من قبل مكتبة الجهة الخارجية. كان التبديل إلى حل مخصص هو الخطوة التالية.

هذا عندما بدأنا العمل مع MongooseIM . MIM هو حل مفتوح المصدر يعتمد على بروتوكول XMPP الراسخ. لقد عملنا مع شركة خارجية Erlang Solutions Limited لإعداد الخلفية الخاصة بنا وتقديم الدعم من خلال تنفيذ الحلول المخصصة.

لوحة القيادة MongooseIM

في البداية ، بدا كل شيء عن المراسلة مختلفًا. في السابق ، كان لدينا جميع احتياجاتنا التي تلبيها SDK وواجهة برمجة تطبيقات REST الخاصة بها. الآن ، باستخدام MongooseIM ، كان علينا قضاء بعض الوقت لفهم طبيعة XMPP وتنفيذ SDK الخاص بنا . اتضح أن خادم XMPP "المجرد" فقط قام بتمرير Stanzas (رسائل XML) بين العملاء في الوقت الفعلي. يمكن أن تكون Stanzas من أنواع مختلفة ، مثل رسائل الدردشة العادية ، والحضور ، والطلبات ، والردود. يمكن إضافة مجموعة متنوعة من الوحدات النمطية إلى الخادم ، على سبيل المثال ، لتخزين الرسائل ، والسماح للعملاء بالاستعلام عنها.

على جانب العميل (Android ، iOS) كانت هناك بعض حزم SDK منخفضة المستوى. لسوء الحظ ، كانوا يعملون فقط كطبقة تتيح الاتصال بـ MongooseIM وبعض الوحدات القابلة للتوصيل التي تسمى XEPs (بروتوكول تمديد XMPP مسؤول ، من بين أمور أخرى ، عن إرسال إشعارات الدفع لكل رسالة). كان على فريقنا تنفيذ البنية الكاملة لمعالجة الرسائل وتخزينها والاستعلام عنها.

ما جاء لإنقاذنا هو مكتبة الطرف الثالث التي استخدمناها سابقًا. كان يحتوي على واجهة برمجة تطبيقات مدروسة جيدًا ، لذلك جعلنا حلنا يعمل بطريقة مماثلة. قمنا بفصل كود XMPP المحدد في SDK الداخلي الخاص بنا مع الواجهة المقابلة لواحد من الحل السابق. نتج عن ذلك تغييرات قليلة فقط في رمز التطبيق الخاص بنا بعد الترحيل.

أثناء تنفيذ MongooseIM ، فوجئنا عدة مرات بالعناصر التي اعتقدنا أنها ستكون قياسية ، ولكن لم تكن متاحة لنا ، حتى بواسطة XEP.

تنفيذ الميزات الرئيسية للدردشة القائمة على XMPP

الطوابع الزمنية

قد تعتقد ، كما فعلنا ، أن الطوابع الزمنية ستكون بسيطة مثل "تلقيت رسالة ، أعرضها على واجهة المستخدم بطابع زمني." كلا ، ليس بهذه السهولة. بشكل افتراضي ، لا تحتوي مقاطع الرسالة على حقل طابع زمني. لحسن حظ فريقنا ، فإن XMPP هو بروتوكول قابل للتوسيع بسهولة. على الواجهة الخلفية ، قمنا بتنفيذ ميزة مخصصة ، بإضافة طابع زمني لكل رسالة مرت عبر خادم MongooseIM. ثم يكون لدى المستلم الطابع الزمني المرفق بالرسالة.

لماذا لا يستطيع المرسل إضافة طابع زمني بنفسه؟ حسنًا ، لا نعرف ما إذا كان لديهم الوقت الصحيح المحدد على هواتفهم.

لماذا لا يوجد أي XEP لذلك؟ ربما لأن XMPP هو بروتوكول في الوقت الفعلي ، لذلك نظريًا يتم تلقي كل رسالة يتم إرسالها على الفور.

تحرير: كما أشار فلوريان شماوس: "يوجد بالفعل واحد ، على الرغم من أنه يمكن تفويته بسهولة بسبب اسمه المربك: XEP-0203: تأخر التسليم." يضيف طابعًا زمنيًا إلى رسالة فقط إذا تأخر تسليمها. خلاف ذلك ، تم إرسال الرسالة الآن.

الرسائل دون اتصال

عندما يتم تسجيل دخول كلا المستخدمين إلى التطبيق ، يمكنهم إرسال رسائل إلى بعضهم البعض في الوقت الفعلي. ولكن ماذا لو كان أحدهم غير متصل بالإنترنت؟ الإجابة السريعة هي: يجب تخزين الرسائل مؤقتًا في الواجهة الخلفية . تتولى ميزة الرسائل في وضع عدم الاتصال هذا العمل وترسل جميع مقاطع الفيديو المخزنة مؤقتًا إلى المستخدم بمجرد تسجيل الدخول مرة أخرى.

ولكن بعد ذلك تبرز عدة أسئلة:

  • إلى متى يجب تخزين هذه الرسائل مؤقتًا؟
  • كم منهم؟
  • هل يجب إعادة إرسالها بعد تسجيل الدخول مرة أخرى؟ لكنها ستغرق العميل بالرسائل ، أليس كذلك؟
  • ماذا لو قام المستخدم بتسجيل الدخول فقط ، لكنه لم يدخل الدردشة بالرسائل الجديدة. هل ذهبوا جميعا؟
  • ماذا لو قام المستخدم بتسجيل الدخول على أجهزة متعددة؟

أصبح من الواضح أن ميزة "الرسائل دون اتصال" كانت قادرة فقط على إرسال الرسائل إلى الجهاز الأول الذي يعود للاتصال بالإنترنت مرة أخرى ، وبعد ذلك ستفقد هذه الرسائل لجميع الأجهزة الأخرى. قررنا تجاهل هذه الميزة ، وتخزين الرسائل على الواجهة الخلفية لـ XMPP بطريقة مختلفة ومستمرة.

إدارة أرشيف الرسائل (MAM)

MAM هو تخزين على الخادم للرسائل. عند تسجيل دخول العميل ، يمكنه الاستعلام عن الرسائل في الخادم. يمكنك الاستعلام عن طريق الصفحات ، يمكنك الاستعلام عن طريق التواريخ. إنه مرن - يمكنك حتى الاستعلام عن صفحة قبل أو بعد رسالة بمعرف معين ، وإضافة عوامل تصفية للرسائل من المحادثة بالضبط.

ولكن هنا تكمن المشكلة. يتم تخزين رسائل الدردشة العادية ملفوفة داخل رسائل MAM ، والتي لها معرفات فريدة خاصة بها. عندما يتلقى المستخدم رسالة دردشة في بث ، فإنها لا تحتوي على معرف MAM. عليهم الاستعلام من MAM للحصول عليه.

الاسترداد من MAM هو طلب شبكة ، مما يعني أنه قد يستغرق وقتًا طويلاً نسبيًا. عندما يدخل المستخدم محادثة ، فإنه يريد أن يرى الرسائل على الفور. لذلك نحتاج أيضًا إلى قاعدة بيانات محلية .

عندما يتلقى المستخدم رسالة في دفق (رسالة عبر الإنترنت) ، فإننا نحفظها في قاعدة البيانات المحلية ونعرضها للمستخدم. بهذه الطريقة ، نعرض الرسائل التي تصل في الوقت الفعلي بسرعة إلى المستخدم.

بالإضافة إلى ذلك ، في كل مرة يدخلون فيها إلى شاشة الدردشة ، نقوم بتنزيل جميع الرسائل من الآن إلى أحدث رسائل MAM المخزنة في قاعدة البيانات المحلية لتلك المحادثة ووضعها في قاعدة بيانات ، متجاهلين التكرارات.

هذه هي الطريقة التي نتعامل بها مع تخزين الرسائل القديمة. أيضًا ، نحن على يقين من وجود مجموعة كاملة من الرسائل في قاعدة البيانات لمحادثة محددة بين الرسالة الأولى والأخيرة من MAM.

لتتبع الرسائل التي تم تنزيلها من MAM ، أضفنا خاصيتين إلى كيانات المحادثة:

  1. معرف MAM لأحدث رسالة MAM في قاعدة البيانات
  2. معرّف MAM لأقدم رسالة MAM في قاعدة البيانات

سيكون التعامل مع مجموعات ممزقة من رسائل MAM في قاعدة بيانات محلية مشكلة كبيرة.

بالإضافة إلى ذلك ، فإن وجود هاتين الخاصيتين لكل محادثة يسمح لنا بتخزين رسائل الدردشة العادية في قاعدة البيانات مع تجاهل الغلاف - رسالة MAM. وعندما يدخل المستخدم الدردشة ، يمكننا عرض أحدث الرسائل من قاعدة البيانات وفي الخلفية جلب الرسائل المفقودة من MAM.

صندوق الوارد

يحتاج كل تطبيق قائم على الدردشة إلى شاشة بها قائمة من الدردشات - مكان يمكنك فيه رؤية الأسماء والرسائل الأخيرة وعدد الرسائل غير المقروءة. يجب أن يكون هناك حل لذلك!

في الواقع ، لا يوجد… هناك شيء يسمى "قائمة" - يمكن أن تحتوي على قائمة مستخدمين تم وضع علامة عليهم باسم "أصدقاء". لسوء الحظ ، لا توجد رسالة أخيرة ولا يوجد عدد رسائل غير مقروءة مرفق بها. بالتأكيد ، يمكنك الحصول على المعلومات المطلوبة من الواجهة الخلفية على شكل أجزاء. في البداية ، أردنا أن نفعل ذلك بهذه الطريقة ، لكنه سيعمل ببطء ويكون معقدًا. وذلك عندما بدأنا العمل مع Erlang Solutions على ميزة Inbox ، والتي تشق طريقها أيضًا لفتح المصدر.

الدردشة المستندة إلى XMPP - شاشة البريد الوارد
شاشة صندوق الوارد - يتم توفير جميع بيانات الدردشات بواسطة ميزة البريد الوارد

عندما يتصل المستخدم بالواجهة الخلفية لـ XMPP ، يجلب التطبيق صندوق الوارد الخاص به ، والذي يحتوي على جميع محادثات هذا المستخدم - المحادثات الفردية والمحادثات الجماعية. كل واحد منهم لديه آخر رسالة مرفقة به وعدد من الرسائل غير المقروءة. يقوم التطبيق بحفظ البريد الوارد بالكامل في قاعدة البيانات المحلية. عندما يكون المستخدم في التطبيق ، وتصل رسالة جديدة ، نقوم بتحديث حالة البريد الوارد محليًا. بهذه الطريقة لا يحتاج التطبيق إلى جلب البريد الوارد لكل رسالة جديدة.

ملخص

توفر بعض حلول الدردشة التابعة لجهات خارجية مستوى عالٍ من التجريد. هذا جيد إذا كنت تريد إنشاء تطبيق دردشة بسيط. من خلال تنفيذ الحل الخاص بنا المستند إلى XMPP في تطبيق Forward ، تمكنا من الحصول على وصول أفضل على المستوى المنخفض ، مما جعل حل المشكلات أسهل بكثير. بالتأكيد ، استغرق الأمر بعض الوقت ، لكننا نعلم الآن أنه يمكننا تقديم أي ميزة مخصصة لمساعدة الأطباء في المملكة المتحدة على التواصل بطريقة آمنة وسهلة معتمدة من NHS.

تتمحور المراسلة حول الأداء العالي والتواصل في الوقت الفعلي. من خلال التبديل إلى MIM ، تمكنا من تحسين كل جزء من الحل لتحسين السرعة والموثوقية والثقة في النهاية. حاليًا ، لدينا الشفرة بالكامل ، لذا من السهل تعقبها. أيضًا ، نحن بعد مرحلة الاستقرار وقد انخفض عدد التقارير المرتبطة بالرسائل بشكل كبير. يسعد المستخدمون بقدرتهم على الوثوق بالمنصة.

كان تصميم وكتابة SDK الخاص بنا مهمة صعبة وقد أحببناها. كان شيئًا مختلفًا عن التطبيقات البسيطة حيث تحتاج إلى جلب البيانات من الخادم وإظهارها على الشاشة. أثناء التنفيذ ، فهمنا العديد من خيارات التصميم الخاصة بواجهة برمجة تطبيقات مكتبة الجهات الخارجية التي استخدمناها سابقًا. لماذا ا؟ لأننا واجهنا نفس المشكلات.