انتقل إلى المحتوى

المحركات

اختيار المحرك

تخزن المحركات الثلاثة الشيء نفسه: معرّف UUIDv7 ومصفوفة بيانات، لكن طريقة تنظيمها على القرص تختلف. ويحدد هذا التنظيم ما يناسب كل محرك:

DocStore SegmentedLog Queue
على القرص ملف JSONC واحد لكل سجل، مع تقسيم لاحقة UUID مقاطع إلحاقية فقط من أسطر JSON مسبوقة بالطول وبصمة التحقق، مع بيان سجل أحداث واحد إلحاقي فقط
الكتابة استبدال ذري للملف لكل سجل عمليات إلحاق ببصمات تحقق؛ تُلحق التعديلات والحذوفات كمدخلات جديدة، وتُستعاد المساحة عبر compact() إلحاق ببصمة تحقق لكل حدث في قائمة الانتظار
القراءة get() حسب المعرّف، واستعلامات مفهرسة مسح بالمؤشر والنطاق الزمني، وget() عبر فهرس الحالة claim() بترتيب الإدراج في قائمة الانتظار
الاستخدام الأمثل القراءات المباشرة وعمليات البحث المفهرسة مهما كان حجم المجموعة تدفقات كثيفة الإلحاق تصل إلى نحو 1M سجل توزيع مهام دائم بين العمليات
نقطة الضعف مسح الحقول غير المفهرسة بعد نحو 10k سجل تكرار إعادة كتابة سجل واحد (تشغل الإصدارات القديمة مساحة حتى الدمج) ليس مخزنًا عامًا للسجلات؛ تُحذف الحمولات بعد اكتمال المهمة

يشترك DocStore وSegmentedLog في واجهة الاستعلامAPI السلسة نفسها: تعمل سلسلة where() نفسها على أي من المحركين، ولا يختلف إلا التنفيذ. ويمكن لـDocStore الإجابة باستخدام فهارسه الثانوية، بينما يرشح SegmentedLog النتائج أثناء مسح المقاطع. أما Queue فيعتمد على المطالبة ولا يدعم الاستعلام: يطالب العمال claim() بالمهمة التالية بدلاً من ترشيح المهام.

إرشادات عامة:

  • السجلات التي تجلبها أو تحدّثها أو تحذفها منفردة وتستعلم عنها حسب الحقل: DocStore. أضف فهارس للحقول التي ترشح النتائج وفقها.
  • الأحداث أو الإصدارات التي تضيفها غالباً وتقرأها بالترتيب أو ضمن نطاق زمني: SegmentedLog.
  • المهام التي ينقلها المنتجون إلى عمليات العاملين: Queue. عمليات المطالبة والإكمال آمنة عند تعدد العمليات، كما توزع claimMany()/completeMany() تكلفة القفل وfsync على دفعات.
  • عمليات الربط أو البحث أو إعداد التقارير عن أي مجموعة: أضف مرآة SQL. تظل الملفات مرجعية؛ والمرآة إسقاط قابل لإعادة البناء في SQLite أو MySQL.

يمكن تركيب المحركات معاً: فهي لا تشترك إلا في المجلد الجذر، لذا يمكن لتطبيق واحد حفظ المحتوى في DocStore وسجل التدقيق في SegmentedLog والعمل في الخلفية في Queue ضمن جذر التخزين نفسه.

DocStore

DocStore مخصص للقراءات المفردة والمسح البسيط للسجلات الدائمة. ويكتب ملف JSONC واحداً لكل سجل:

PHP
$store = new Storh\DocStore($root, 'articles');
$record = $store->put(['slug' => 'hello', 'published' => true]);
$same = $store->get($record->id());

تُقسم ملفات السجلات حسب أحرف UUID الأخيرة لتوزيع دفعات الكتابة ذات UUIDv7 على المجلدات:

Text
articles/data/2d/018bcfe5-6800-7000-8000-2d5dba6274da.jsonc

SegmentedLog

SegmentedLog مخصص للسجلات كثيرة الإضافة وقراءات المؤشر وقراءات النطاق الزمني. تُكتب السجلات في المقطع النشط، سطر واحد لكل سجل بالصيغة <byte-length>\t<xxh32>\t<json> (راجع الذرية). تستخدم ملفات المقاطع امتداد .ndjson، لكن بادئة الطول والمجموع الاختباري تعني أن أدوات NDJSON العادية لا تستطيع قراءتها؛ اقرأ السجلات باستخدام stream() أو أداة إنشاء الاستعلامات. وعند امتلاء المقاطع، تتحول إلى مقاطع مختومة ذات فهارس متناثرة.

PHP
$events = new Storh\SegmentedLog($root, 'events');
$events->put(['type' => 'user.created']);
$events->compact();

قائمة الانتظار

Queue مخصص لقوائم انتظار العمل الدائمة عالية الإنتاجية. تكتب عمليات enqueue وclaim وcomplete وrequeue وpurge أحداثاً إلحاقية فقط في queue.log؛ وتُعاد قراءة حالة قائمة الانتظار إلى الذاكرة عند فتحها. وتوزع الأساليب الدفعية تكلفة القفل والتفريغ على مهام كثيرة. يزداد حجم السجل مع كل حدث؛ ويعرض stats() حجمه الحالي بالبايت.

PHP
$queue = new Storh\Queue($root, 'mail');
$queue->enqueue(['to' => 'person@example.test']);
$job = $queue->claim();

المتانة والتزامن

ينشر storh كتابات الملفات باستخدام إعادة تسمية ذرية داخل المجلد الهدف. ويزيل كل من إعادة الفتح وrepair() الملفات المؤقتة المتروكة التي انتهت عملية مالكها، مع ترك ملفات العمليات الكاتبة النشطة كما هي. وتجعل علامات الكاتب هذا الفحص ثابت الزمن، لذلك لا يُمسح المخزن إلا بعد تعطل.

تكتب SegmentedLog وQueue أسطر سجل محمية بالطول وبقيمة التحقق. تؤدي إعادة الفتح أو الإصلاح إلى اقتطاع النهايات المبتورة عند آخر حدث معتمد، وإعادة بناء الحالة في الذاكرة من محتويات السجل الدائمة. تُسلسَل عمليات الكتابة إلى السجل والصف باستخدام أقفال نظام الملفات.

تُسلسَل عمليات التعديل في DocStore باستخدام قفل كتابة على مستوى المجموعة، بحيث تُحدَّث ملفات السجلات والفهارس الثانوية ضمن حد اتساق واحد عبر العمليات. تكون الكتابات المتزامنة إلى معرّفات سجلات مختلفة آمنة، وفق افتراضات إعادة التسمية الذرية نفسها في نظام الملفات. أما الكتابات المتزامنة إلى المعرّف نفسه، فتسود فيها آخر عملية إعادة تسمية.

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