الاستعلامات
إن RecordQuery هو مرشح تدفقي يُستخدم مع stream(). وهو يغطي أنماط الوصول القائمة على الإلحاق: الاستئناف بعد مؤشر، وقراءة نطاق زمني، والتصفية بمساواة الحقول، والتوقف عند حد معين. للمرشحات الأكثر تعقيدًا والترتيب وعمليات البحث المدعومة بالفهرس، استخدم منشئ الاستعلامات؛ أما لكل ما يمكن أن يفعله foreach عادي على تدفق، فـRecordQuery هو الخيار الأقل كلفة.
RecordQuery غير قابل للتغيير. يعيد كل مُعدِّل استعلامًا مستنسخًا:
$query = Storh\RecordQuery::all()
->after($lastSeenId)
->time_range_ms($fromMs, $untilMs)
->where_equal('kind', 'page')
->limit(100);
foreach ($store->stream($query) as $record) {
// Records are yielded lazily.
}
يستخدم after() وtime_range_ms() ترتيب UUID، لذا لا يحتاجان إلى حقل طابع زمني في بيانات السجل. وفي SegmentedLog يتجاوزان أيضًا العمل غير اللازم: فلا تُفتح الأجزاء التي يقع نطاق معرّفاتها خارج النافذة، وتبحث الفهارس المتباعدة لكل جزء قرب أول سجل مطابق بدلًا من المسح من البداية.
يقارن where_equal() حقل بيانات من المستوى الأعلى مع ===، ويقبل القيم المفردة أو null. يطابق مرشح null السجلات التي يكون فيها الحقل موجودًا وقيمته null؛ أما السجلات التي لا تحتوي على الحقل فلا تطابقه.
تقسيم الصفحات بالمؤشر
تُرتَّب المعرّفات حسب وقت الإنشاء، لذا يكون آخر معرّف في الصفحة هو المؤشر للصفحة التالية:
$page = iterator_to_array($store->stream(
Storh\RecordQuery::all()->after($lastSeenId)->limit(100)
), false);
$lastSeenId = [] === $page ? $lastSeenId : end($page)->id();
التعامل مع السجلات التالفة
يتوقف المسح عند أول سجل يتعذر قراءته افتراضيًا. استخدم continue_on_error() عندما تريد أن يتجاوزه المسح ويبلغ عن الإخفاق بدلًا من ذلك:
$query = Storh\RecordQuery::all()->continue_on_error(
static function (string $location, Throwable $error): void {
error_log($location . ': ' . $error->getMessage());
},
);
الموقع هو معرّف السجل لـ DocStore وsegment-file:byte-offset لـ SegmentedLog. repair() هي الأداة المستخدمة فعليًا لتنظيف السجلات التالفة؛ راجع CLI.