Saudi commerce · Salla API engineering

استرجاع طلبات سلة: Pagination متسلسلة دون فقد البيانات

تصميم إنتاجي لاستيراد تاريخ طلبات سلة مع احترام تسلسل الصفحات ونافذة Pagination المخزنة وقدرة API لكل متجر.

المسار المرتبطهندسة التجارة الإلكترونية
رسم تقني أصلي لاسترجاع طلبات سلة عبر نوافذ زمنية وصفحات متسلسلة ومخزن Transactional ونقطة مصالحة.
تصوّر بصري للفكرة — يتبعه شرح ومخطط تنفيذي داخل المقال.

يجب أن تحافظ عملية الاسترجاع التاريخي لطلبات سلة على تسلسل جلسة الصفحات، لا أن تعامل أرقام الصفحات كمهام مستقلة. توضح وثائق List Orders الحالية أن الصفحات تُطلب بالترتيب، وأن القفز فوق صفحة قد يعيد نتيجة فارغة، وأن التسلسل ينبغي أن يكتمل داخل نافذة Cache مدتها 15 دقيقة، مع استخدام فلاتر التاريخ لتقليل البيانات. لذلك يكون التصميم الآمن نافذة زمنية قصيرة يملكها Worker واحد، مع Checkpoint دائم بعد اكتمال كل شريحة زمنية، لا تشغيل الصفحات من 1 إلى N بالتوازي.

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

ابدأ من العقد الموثق

توصي وثائق List Orders في سلة بطلب الصفحات بالتسلسل، وتحدد 30 كأقصى حجم صفحة لهذا المسار، وتطلب إكمال التسلسل داخل نافذة Pagination مخزنة مؤقتًا لمدة 15 دقيقة، مع فلاتر from_date وto_date. ويشرح دليل Pagination العام كائن Pagination ومعاملات page وper_page، بينما يوثق دليل Rate Limiting ميزانيات طلبات تختلف حسب الخطة وترويسات X-RateLimit-Limit وX-RateLimit-Remaining وRetry-After وX-RateLimit-Reset.

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

يجب أن يصف Checkpoint الدائم وقت الأعمال وحالة المعالجة: معرف المتجر، بداية ونهاية نافذة مغلقة، مجموعة الفلاتر، آخر Timestamp أو Order ID تمت مصالحته، وقت آخر تحقق ناجح، ومعرف Run. أما Page Number فهو تقدم مؤقت داخل Lease حية فقط.

اختر نوافذ زمنية محدودة

لا تطلب من جلسة Pagination واحدة تغطية تاريخ متجر نشط بالكامل. قسّم التاريخ إلى نوافذ مغلقة—يوم أو ساعة أو مدة أصغر تتكيف مع الحجم—وأكمل نافذة قبل الانتقال إلى التالية. استخدم أكبر مدة تنتهي باستمرار قبل حد 15 دقيقة بهامش واضح وفق حجم الطلبات وميزانية المتجر.

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

قد يحتاج يوم حملة كثيفة إلى نوافذ خمس دقائق، بينما يكفي يوم كامل لمتجر هادئ. اجعل التقسيم Adaptive: إذا انتهت النافذة بسرعة وبقيت ميزانية، وسّع التالية بحذر؛ وإذا اقتربت من Deadline أو ظهر ضغط Rate Limit، صغّر التالية. لا تغيّر الفلاتر أو Page Size في منتصف المرور الحي.

اجعل لكل متجر ونافذة مالكًا واحدًا

احصل على Lease بمفتاح المتجر والنافذة قبل طلب الصفحة الأولى. تمنع Lease عاملين من التسابق داخل جلسة متسلسلة واحدة. خزّن Run ID وFilter Hash وPage Size وانتهاء Lease ووقت البدء والصفحة المؤقتة الحالية. جدّد Lease بعد كتابة صفحة كاملة Transactionally.

إذا تعطل Worker، لا يبدأ البديل من الصفحة المخزنة بلا تحقق. افحص هل ما تزال الجلسة الأصلية قادرة على الانتهاء داخل نافذة Cache وهل كل Request Parameter مطابق. إذا تعذر الإثبات، ابدأ نافذة الأعمال المحدودة نفسها من الصفحة 1 واعتمد على Idempotent Upserts. إعادة قراءة نافذة صغيرة تستهلك طلبات؛ تخطي طلبات بصمت يفسد الصحة.

يمكن تشغيل متاجر مختلفة بالتوازي لأن ميزانياتها وجلساتها مستقلة، لكن اترك المرور داخل Store Window واحدة متسلسلًا. ويمكن لطابور عالمي تطبيق العدالة حتى لا يؤخر Backfill ضخم Webhooks الحية أو قراءات التصحيح الصغيرة. يشرح دليل ميزانية Salla API القبول لكل متجر والجدولة العادلة؛ والفرق هنا أن Page Concurrency يجب أن تبقى واحدًا داخل مرور List Orders.

الصفحات تقدم مؤقت داخل نافذة حية؛ أما Checkpoint الدائمة فهي شريحة وقت الأعمال بعد المصالحة.
الصفحات تقدم مؤقت داخل نافذة حية؛ أما Checkpoint الدائمة فهي شريحة وقت الأعمال بعد المصالحة. اضغط لعرض أكبر

اكتب كل صفحة بصورة Idempotent

عالج الصفحة داخل Database Transaction. نفذ Upsert لكل طلب باستخدام store_id مع Salla Order ID، واحتفظ بـupdated timestamp من المصدر، وارفض Payload أقدم يحاول الكتابة فوق سجل أحدث. خزّن Raw Payload أو Content Hash عندما تكون Auditability مطلوبة. لا تعلم الصفحة مكتملة للـRun الحالي إلا بعد نجاح كل الصفوف والسجلات التابعة.

لا تنفذ Side Effects downstream مباشرة من Pagination Loop. اكتب التغييرات في Outbox داخل Transaction نفسها، ثم انشرها بصورة غير متزامنة. تستطيع الصفحة المعادة إنتاج Event Key حتمي نفسه ويتجاهل المستهلك التكرار. من دون هذا الحد قد تعيد محاولة قاعدة البيانات أمر ERP أو طلب Fulfillment أو إشعار عميل مرتين.

تكفي الحالة التالية لبناء Controller قابل للاستعادة:

{
  "store_id": "merchant-42",
  "window": { "from": "2026-10-01T00:00:00Z", "to": "2026-10-02T00:00:00Z" },
  "filter_hash": "sha256:...",
  "page_size": 30,
  "transient_page": 7,
  "started_at": "2026-10-19T16:00:00Z",
  "lease_until": "2026-10-19T16:02:00Z",
  "run_id": "backfill-01K..."
}

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

اضبط الميزانية من الترويسات لا التخمين

اقرأ Rate Limit Headers من كل استجابة واعرضها Metrics. أبطئ أو توقف قبل وصول Remaining إلى صفر لأن المتجر نفسه قد يحتاج Live Reads أو Writes. احترم Retry-After عند وجودها؛ يعرّف HTTP الترويسة كمدة انتظار العميل قبل طلب لاحق. أضف Jitter حتى لا تستيقظ عمليات كثيرة في اللحظة نفسها.

احجز جزءًا من قدرة المتجر للمرور الحرج. عادة تكون Backfill أقل أولوية من تأكيد دفع أو تحديث حالة طلب أو Webhook Reconciliation. يستطيع Scheduler توزيع Tokens بين Live وReconciliation وHistorical من دون تثبيت Rate واحد لكل خطط التجار. عامل الحدود غير الموثقة كقيم قابلة للتغيير واستمد السلوك من الترويسات الحالية والاستجابات المرصودة.

عند 429 لا تتقدم إلى الصفحة التالية. انتظر حسب Retry-After أو Reset Header، وجدّد Lease فقط إذا بقي وقت آمن، وأعد النافذة عندما يصبح التسلسل غير محسوم. عند 401 توقف وجدّد التفويض عبر مسار Token المعتاد؛ التكرار بنفس Credential يهدر النافذة. عند 5xx أو Transport Timeout أعد الصفحة نفسها بـBounded Exponential Backoff، ثم أعد النافذة إذا تعذر إثبات الاستمرارية.

صالح Webhooks مع Backfills

تحل Webhooks وBackfills مشكلتين مختلفتين. توفر Webhooks إشارات تغيير منخفضة التأخير، وتصلح قراءة الطلبات المحدودة التسليمات المفقودة أو المتأخرة أو الفاشلة. مرر الاثنين عبر Order Projection واحدة Idempotent حتى لا يقرر ترتيب الوصول الحقيقة. قارن Updated Timestamps واحتفظ بمصدر آخر نسخة مطبقة.

دورة إنتاج مناسبة هي: استهلاك Webhooks باستمرار، وإعادة قراءة نافذة تصحيح قصيرة دوريًا، وتشغيل Historical Backfills بأولوية منخفضة. بعد اكتمال نافذة تاريخية نفذ Reconciliation Query أو Count Check مناسبًا لنموذجك المحلي. لا تعلن النجاح لمجرد الوصول إلى totalPages؛ تحقق من عدم وجود Page Transaction فاشلة أو Lease منتهية أو Rate-limit Interruption غير محلولة.

لآليات التسليم راجع دليل استعادة Webhooks في سلة وزد. وإذا كان التكامل يزامن المخزون أيضًا، افصل إدخال الطلب عن محاسبة Stock Movements؛ يوضح تصميم تدقيق مخزون سلة وERP لماذا Ledger دائمة أكثر أمانًا من استبدال آخر كمية.

أفضل الممارسات والأخطاء الشائعة

استخدم Date Filters وFilter Hash ثابتة ومالكًا واحدًا لكل Store Window وطلبات صفحات متسلسلة وIdempotent Upserts وOutbox. راقب مدة النافذة والصفحات لكل نافذة ونسبة التكرار وعدد Replays واستجابات 429 والميزانية المتبقية وفقد Lease وReconciliation Lag. أنشئ Alert قبل اقتراب التشغيل المعتاد من حد 15 دقيقة.

تجنب Job منفصلة لكل صفحة. لا تخزّن Page 37 بوصفها Checkpoint الوحيدة. لا تغير per_page أثناء Run. لا تستخدم Workers متوازية لمرور واحد. لا تسمح لاستيراد تاريخي باستهلاك كل ميزانية المتجر. لا تعتبر صفحة فارغة بعد القفز نهاية البيانات. ولا تحرك Durable Watermark قبل نجاح المصالحة.

متى لا تستخدم هذا النمط؟

استخدم Webhook-only عندما يبدأ التكامل من الآن ولا يحتاج تاريخًا وله آلية موثقة لتعافي التسليمات المفقودة. واستخدم Export Orders الموثقة في سلة عندما تكون الحاجة تقرير CSV أو XLSX للبشر لا Application Projection؛ فمسار التصدير له دلالات اكتمال وتسليم مختلفة. واستخدم Query ضيقة عندما يعرف الدعم طلبًا واحدًا، لا مرورًا كاملًا.

يناسب هذا النمط ERP أو Warehouse أو Analytics Store أو Search Index تحتاج تاريخ طلبات محليًا موثوقًا. وهو يتعمد استبدال Page Parallelism بتسلسل قابل للإثبات، ثم يستعيد Throughput بتقسيم الزمن وتشغيل متاجر مستقلة بالتوازي. القاعدة الأساسية: ثبّت نوافذ الأعمال دائمًا، واجعل الصفحات مؤقتة، وأعد أي نافذة غير محسومة من الصفحة الأولى.

قائمة تنفيذ قبل الإنتاج

تحقق من عقد سلة الحالي، واختر نافذة تاريخ محافظة، وافرض Lease نشطة واحدة، وثبت الفلاتر وحجم الصفحة، واكتب الصفحات Transactionally، واحجز قدرة للمرور الحي، واحترم Retry-After، واختبر التعطل بعد API Response وبعد Database Commit. أثبت أن Replay لا تكرر Side Effects. وأخيرًا، صالح النافذة المغلقة ثم فقط حرك Durable Watermark.

المراجع الرسمية

تدعم هذه المراجع سلوك الأدوات المذكورة. الأمثلة وقرارات التصميم توضيحية، ويجب تكييفها مع متطلبات المشروع وإصداراته.

إعداد: Noor Yasser

من القرار إلى التنفيذ

تعمل على تحدٍ تقني مشابه؟

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

احجز لقاءً لمدة ٣٠ دقيقةالخدمة المرتبطةهندسة الأنظمة الخلفية وتكاملات APIمشروع من الأعمالمنصة اللوجستيات