- بواسطة x32x01 ||
🔄 ليه الـ Sync مهم جدًا في أي Cross-Platform App؟
الـ Sync من أهم الحاجات في أي Cross-platform application (موبايل + ويب) لأنك لو ما هندلتش الحتة دي صح… هتعيش في دوامة 😅عمرك ما اتلغبطت وانت بتحاول تعرف:
مين اتسجل Local ولسه محتاج يترفع على Server؟ 🤔
هنا بقى بييجي هدف الـ Sync الحقيقي: يخلي التطبيق Offline-first ✅
يعني تقدر تستخدمه من غير نت، ولما النت يرجع… كل حاجة تتزامن تلقائي.
🧠 الفكرة الأساسية: Offline-First + Local Queue
أحسن طريقة شغالة مع Apps كتير هي إنك تبني الـ Sync على:- Local DB (تخزين محلي)
- Operations Queue (op queue) لكل اللي اليوزر بيعمله
- Push / Pull
- Checkpoint بسيط زي lastSyncAt علشان تعرف آخر مرة سحبت/رفعت إمتى 👌
بدل ما تقعد تخمن “إيه اللي اترفَع وإيه اللي لسه”، انت عندك Queue واضحة.
🧾 Flow بسيط وواضح للـ Sync
1) تسجيل كل تغيير محليًا
أي Action اليوزر يعملها (إضافة/تعديل/حذف/مشاهدة…) يتسجل في Local DB كـ Operation:- status = pending
- localTimestamp
- tempId أو sequence علشان تتابع الأحداث بالترتيب
2) كل العمليات تدخل الـ Local Queue
كل حاجة تتجمع في op queue ودي اللي هتعمل منها Push بعدين على دفعات.3) خليك Idempotent (مهم جدًا!)
أي عملية Push لازم تكون Idempotent أو لها idempotencyKeyعلشان لو حصل Retry أو الشبكة قطعت، ما تكررش نفس العملية مرتين وتبوّظ البيانات 🔁
🚀 وقت النت: Push على دفعات + رد واضح من السيرفر
لما الشبكة تبقى متاحة:- تقرأ أول Batch من الـ Queue (مثلاً 50 عملية)
- تبعتها للسيرفر على endpoint زي: POST /sync/push
- السيرفر يعمل Upserts ويحدد نتيجة كل عملية: accepted - conflict - rejected
ساعتها انت محليًا:
- تعمل status = synced
- وتخزن syncedAt = serverTimestamp
- وتحدّث الـ Records بالمعلومات الرسمية من السيرفر ✅
📥 Pull بالدلتا باستخدام lastSyncAt
بعد الـ Push، تعمل Pull للتغييرات اللي حصلت على السيرفر من آخر مرة:- تبعت lastSyncAt
- السيرفر يرجّع “اللي اتغير بس” (Delta)
- تحدّث الـ Local DB
🔁 Retry + Backoff + حل الـ Conflicts
عشان الـ Sync يبقى محترم فعلًا:- اعمل Retries مع Exponential Backoff
- تعامل مع Conflicts بدل ما تخبيها
- في حالة Merge (زي signup/login):
- ارفع اللي عندك Local الأول
- وبعدها اسحب اللي على السيرفر
🧩 كود توضيحي بسيط: شكل الـ Operation في الـ Queue
// مثال لشكل العملية اللي بتتخزن في الـ local op queue JavaScript:
const op = {
opId: "op_10021",
type: "UPDATE_ITEM",
entity: "wallet",
tempId: "tmp_9f2a",
payload: { name: "Cash", balance: 2500 },
status: "pending",
localTimestamp: Date.now(),
idempotencyKey: "wallet_update_tmp_9f2a_v1"
}; 🧩 كود توضيحي: Push Batch بشكل آمن
JavaScript:
async function pushBatch(ops) {
const res = await fetch("/sync/push", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ops })
});
const result = await res.json();
// مثال: تحديث حالة كل op حسب رد السيرفر
for (const r of result.items) {
if (r.status === "accepted") {
await markSynced(r.opId, r.serverTimestamp, r.mappings);
} else if (r.status === "conflict") {
await markConflict(r.opId, r.reason);
} else {
await markRejected(r.opId, r.reason);
}
}
} ✅ المختصر المفيد اللي يمشيك صح
لو عايز Sync شغال كويس في Cross-platform:- خزّن كل حاجة Local في Queue
- اعمل Push على دفعات
- خُد Mappings + Timestamps الرسمية من السيرفر
- علّم Records محليًا إنها Synced
- اعمل Pull Delta من lastSyncAt
- خلي العمليات Idempotent
- اعمل Retries + Backoff
- تعامل مع الـ Merge والـ Conflicts بوضوح 👌