Offline Queue هي آلية تحفظ عمليات المستخدم محليًا عندما يكون الجهاز غير متصل بالشبكة وترسلها إلى الخادم بعد استعادة الاتصال. بدون قائمة انتظار عدم الاتصال، يفقد المستخدم جميع الإجراءات التي تمت بدون إنترنت، وهو أمر غير مقبول في تطبيقات الجوال. وفقًا لـ Google Developers (2025), يؤدي تطبيق بنية offline-first إلى زيادة الاحتفاظ بالمستخدمين بنسبة 30% في المناطق ذات الإنترنت غير المستقر.
الخلاصة
Offline Queue هي مجموعة مرتبة من العمليات (إنشاء، تحديث، حذف) يحفظها التطبيق محليًا عندما لا يكون للجهاز وصول إلى الشبكة. بمجرد استعادة الاتصال، ترسل قائمة الانتظار العمليات إلى الخادم بنفس الترتيب الذي نفذها به المستخدم.
تخيل سيناريو: مستخدم مراسلة يكتب رسائل في مترو الأنفاق بدون إنترنت. كل نقرة على «إرسال» تُضاف إلى Offline Queue. عندما يخرج القطار من النفق وتظهر الشبكة، تُرسل جميع الرسائل تلقائيًا. تجربة المستخدم — سلسة: لا يلاحظ أنه كان غير متصل، باستثناء تأخير بسيط في الإرسال.
وفقًا لـ Uber Engineering (2024), تعالج قائمة انتظار عدم الاتصال الخاصة بهم أكثر من 2 مليون عملية يوميًا في المناطق ذات جودة الاتصال الرديئة. تستخدم قائمة الانتظار التخزين المحلي Room بترتيب FIFO وآلية تسليم مضمونة exactly-once.
data class QueuedOperation(
val id: String,
val type: OperationType,
val endpoint: String,
val payload: String,
val timestamp: Long,
val retryCount: Int = 0,
val idempotencyKey: String
)
تحتوي كل عملية على جميع البيانات اللازمة لإعادة الإرسال: نقطة النهاية، نص الطلب، الطابع الزمني و idempotencyKey. قاعدة بيانات Room تضمن استمرارية قائمة الانتظار عند إعادة تشغيل التطبيق وأعطال نظام التشغيل.
ضمان التسليم — الهدف الرئيسي لقائمة الانتظار. يجب أن يكون المستخدم واثقًا من أن إجراءه (إرسال رسالة، إعجاب، طلب) سيتم تنفيذه، حتى لو كانت الشبكة غير متوفرة في تلك اللحظة. Offline Queue مع آلية إعادة المحاولة تضمن التسليم النهائي.
تحسين تجربة المستخدم في ظروف الاتصال الرديئة — وفقًا لـ GSMA Mobile Economy Report (2025), حوالي 40% من مستخدمي الجوال في العالم لديهم اتصالات إنترنت غير مستقرة. Offline Queue تجعل التطبيق قابلاً للاستخدام في مترو الأنفاق والمصاعد والمناطق النائية — في كل مكان تكون فيه الاتصالات متقطعة.
تقليل فقدان البيانات — بدون قائمة انتظار، تُفقد جميع الإجراءات التي تتم في وضع عدم الاتصال. يمكن للمستخدم ملء نموذج طويل، والنقر على «إرسال» ورؤية خطأ في الشبكة — يُفقد كل الإدخال. تحفظ Offline Queue البيانات وترسلها عند أول فرصة. الحفظ التلقائي في Google Docs هو مثال كلاسيكي لقائمة انتظار عدم الاتصال للمستندات.
المزامنة غير المتزامنة — تسمح قائمة الانتظار للتطبيق بعدم حظر واجهة المستخدم أثناء الإرسال. يواصل المستخدم العمل بينما يعالج مدير المزامنة قائمة الانتظار في الخلفية. يتبع هذا مبادئ الهندسة التفاعلية ويحسن استجابة الواجهة.
ثلاث طبقات لقائمة الانتظار: التخزين (الاستمرارية)، المجدول (scheduler) والمنفذ. التخزين — Room مع جدول QueuedOperation. المجدول — WorkManager (Android) أو BGTaskScheduler (iOS) الذي يبدأ المزامنة عند ظهور الشبكة. المنفذ — مكرر FIFO تسلسلي يرسل العمليات واحدة تلو الأخرى.
ترتيب المعالجة — أمر بالغ الأهمية لاتساق البيانات. إذا أنشأ المستخدم سجلاً ثم حرره، يجب إرسال كلتا العمليتين بنفس الترتيب. وإلا، سيتلقى الخادم أولاً تحديثًا لسجل غير موجود — خطأ. FIFO تسلسلي — ترتيب صارم مع التحكم في التبعيات بين العمليات.
استراتيجية الدمج — إذا كانت قائمة الانتظار تحتوي على CREATE يتبعه فورًا DELETE لنفس الكائن، يمكن حذف كلتا العمليتين بدون إرسال: الحالة النهائية هي أن الكائن لم يتم إنشاؤه. وبالمثل، يمكن دمج CREATE + UPDATE في CREATE واحد بأحدث البيانات. تحسين قائمة الانتظار يقلل عدد طلبات HTTP ويسرع المزامنة.
وفقًا لـ Android Developers (2025), WorkManager هو الطريقة المفضلة لمعالجة Offline Queue على Android: يضمن التنفيذ حتى بعد إعادة تشغيل الجهاز، ويدعم قيود الشبكة، ويسمح بتكوين سياسات إعادة المحاولة عبر NetworkType.CONNECTED.
class SyncWorker(
private val context: Context,
private val params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result = runCatching {
queueRepository.processNextBatch(batchSize = 10)
Result.success()
}.getOrDefault(Result.retry())
}
يقوم CoroutineWorker بمعالجة دفعات العمليات ويعيد Result.retry() عند الفشل — يعيد WorkManager المحاولة تلقائيًا مع تأخير أسي. هذه هي أبسط طريقة للحصول على Offline Queue موثوقة على Android.
Exponential Backoff — استراتيجية إعادة محاولة قياسية بفواصل زمنية متزايدة: 2 ثانية، 4 ثوانٍ، 8 ثوانٍ، 16 ثانية وهكذا حتى حد أقصى. يمنع هذا التحميل الزائد المتكرر على الخادم إذا كان غير متاح مؤقتًا. توفر مكتبة Java Resilience4j (2024) تنفيذًا جاهزًا لإعادة المحاولة مع backoff قابل للتكوين.
الحد الأقصى لعدد المحاولات — معلمة حرجة. إذا فشلت العملية بعد 5–10 محاولات، فإن المزيد من إعادة المحاولة يكون مضيعة وغير مفيد. يُوصى باستخدام dead letter queue: بعد استنفاد المحاولات، تُنقل العملية إلى جدول منفصل للتحليل اليدوي. وفقًا لـ Microsoft Patterns & Practices (2024), تعمل dead letter queue على تبسيط تصحيح مشكلات المزامنة وتمنع العمليات الخاطئة من حظر قائمة الانتظار.
Jitter — التباين العشوائي — إضافة رقم عشوائي إلى فترة backoff. إذا استعاد ألف جهاز الشبكة في وقت واحد بعد انقطاع، تبدأ جميعها في المزامنة في نفس الوقت. يعمل Jitter على توزيعها على الوقت، مما يمنع Cache Stampede على الخادم. Jitter كامل: delay = random(0, backoff) — موصى به من AWS (2024) لعملاء API.
Last Write Wins (LWW) — أبسط استراتيجية: في حالة التعارض، تفوز العملية ذات الطابع الزمني الأحدث. يتطلب LWW مزامنة الوقت — يجب إنشاء الطابع الزمني على الخادم أو استخدام ساعة منطقية (ساعات لامبورت). العيب: يمكن استبدال بيانات مستخدم ببيانات مستخدم آخر بدون تحذير.
OT (التحويل التشغيلي) — الخوارزمية المستخدمة من قبل Google Docs وFigma للتحرير التعاوني في الوقت الفعلي، بما في ذلك وضع عدم الاتصال. يحول OT العمليات بحيث يمكن تطبيقها على أي حالة من المستند، مما يضمن الاتساق بدون أقفال. CRDT (أنواع البيانات المكررة الخالية من التعارض) — بديل لـ OT يكتسب شعبية في تطبيقات الجوال: يتم هيكلة البيانات بحيث يمكن حل التعارضات رياضيًا بدون خادم مركزي.
الدمج المخصص — للتطبيقات ذات نماذج البيانات البسيطة (الملاحظات، جهات الاتصال)، يمكن تنفيذ قواعد دمج مخصصة. على سبيل المثال، لملاحظة: إذا تم تعديل النص في نسختين، دمجهما كسلسلة نصية مع فاصل. تعارض يتم حله بواسطة المستخدم — إذا كان الدمج التلقائي مستحيلاً، اعرض على المستخدم كلا النسختين ودعه يختار. يستخدم Dropbox (2024) هذا النهج لتعارضات الملفات غير المتصلة، منشئًا نسخًا بالبادئة «Conflicted Copy».
مفتاح التماثل — معرف فريد للعملية يستخدمه الخادم لاكتشاف الطلبات المكررة. إذا أرسل العميل نفس الطلب بنفس المفتاح، يعيد الخادم نتيجة العملية المنجزة دون تنفيذها مرة أخرى. هذا مهم بشكل بالغ لـ Offline Queue، حيث تكون إعادة الإرسال ممكنة بسبب أخطاء الشبكة.
تنسيق مفتاح التماثل هو UUID أو تجزئة لمعلمات الطلب. يجب على الخادم تخزين المفاتيح المنجزة مع النتيجة لبعض الوقت (عادة 24 ساعة) لاكتشاف المكررات. API Stripe (2024) هو المثال المرجعي: يُمرر المفتاح في رأس Idempotency-Key، وتعيد الطلبات المتكررة بنفس المفتاح استجابةً مخزنة.
التوليد من جانب العميل — يُنشأ المفتاح على العميل قبل إرسال العملية ويُخزن في جدول QueuedOperation. عند إعادة المحاولة، لا يتغير المفتاح. هندسة exactly-once — الجمع بين مفتاح التماثل على العميل وإزالة الازدواجية على الخادم هو الطريقة الوحيدة لضمان عدم تنفيذ العملية مرتين.
fun createOperation(type: OperationType, payload: String): QueuedOperation =
QueuedOperation(
id = UUID.randomUUID().toString(),
type = type,
endpoint = type.endpoint,
payload = payload,
timestamp = currentTimeMillis(),
idempotencyKey = UUID.randomUUID().toString()
)
تحصل كل عملية على UUID اثنين: واحد — معرف السجل في قائمة الانتظار، والثاني — مفتاح التماثل للخادم. إزالة الازدواجية من جانب الخادم عبر idempotencyKey يضمن أنه حتى عند إعادة الإرسال، لن يتم تكرار الطلب.
الأسئلة الشائعة
التخزين المؤقت يخزن نسخًا من البيانات للقراءة السريعة في وضع عدم الاتصال. Offline Queue تخزن عمليات المستخدم للكتابة اللاحقة على الخادم. التخزين المؤقت يعمل للقراءة، قائمة الانتظار تعمل للكتابة. يمكن لكلا المكونين التعايش في بنية offline-first.
الحد الموصى به — 100–500 عملية. أكثر يخلق خطر تجاوز الذاكرة والمزامنة الطويلة عند استعادة الشبكة. عند تجاوز الحد، يجب على التطبيق تحذير المستخدم واقتراح تحديد أولويات العمليات. حد معقول — 50 عملية تحديث + 10 عمليات إنشاء.
العمليات الأقدم من 7 أيام مع عدم نجاح تُنقل إلى dead letter queue. حللها يدويًا: ربما تغيرت API وأصبحت نقطة النهاية غير موجودة. التنظيف التلقائي — مهمة HealthCheck تُنفذ يوميًا لحذف أو أرشفة العمليات منتهية الصلاحية.
استخدم رسم بياني للتبعيات (DAG): تحتوي كل عملية على قائمة من parentOperationId التي يجب أن تكتمل قبل إرسالها. استعلام Room مع ORDER BY parent يعيد العمليات بالتسلسل الصحيح. الإرسال المتتالي — بعد اكتمال كل عملية، تحقق مما إذا كانت العمليات الفرعية غير محظورة.
استخدم Network Less Tool في Android Emulator أو Network Link Conditioner في iOS Simulator لمحاكاة فقدان الشبكة. اكتب اختبارات تُضيف عمليات إلى قائمة الانتظار في وضع عدم الاتصال، وتستعيد الاتصال، وتتحقق من إرسال جميع العمليات ومعالجتها بواسطة الخادم.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.