Mesin
Memilih mesin
Ketiga mesin menyimpan hal yang sama, yaitu ID UUIDv7 beserta array data, tetapi menyusunnya secara berbeda di disk. Susunan tersebut menentukan keunggulan tiap mesin:
| DocStore | SegmentedLog | Queue | |
|---|---|---|---|
| Di disk | satu file JSONC per record, dipecah berdasarkan UUID-tail | segmen append-only dengan baris JSON berawalan panjang dan checksum, beserta manifest | satu log peristiwa append-only |
| Penulisan | penggantian file atomik per record | append dengan checksum; penimpaan dan penghapusan menambahkan entri baru, yang ruangnya dibebaskan melalui compact() |
append ber-checksum untuk setiap peristiwa antrean |
| Pembacaan | get() berdasarkan ID, kueri berindeks |
pemindaian kursor dan rentang waktu, get() melalui indeks status |
claim() sesuai urutan enqueue |
| Keunggulan | pembacaan titik dan pencarian berindeks untuk ukuran koleksi apa pun | stream intensif append hingga sekitar 1M record | distribusi pekerjaan persisten antarproses |
| Kelemahan | pemindaian field tanpa indeks pada koleksi di atas sekitar 10k record | penulisan ulang satu record yang sering (versi lama memakai ruang hingga pemadatan) | bukan penyimpanan record umum; payload dihapus setelah pekerjaan selesai |
DocStore dan SegmentedLog berbagi antarmuka kueri API yang sama: rangkaian where() yang sama berjalan pada kedua mesin dan hanya cara eksekusinya yang berbeda. DocStore dapat menjawab dari indeks sekundernya, sedangkan SegmentedLog memfilter sambil memindai segmen. Queue menggunakan klaim, bukan kueri: worker claim() pekerjaan berikutnya alih-alih memfilter pekerjaan.
Panduan umum:
- Catatan yang Anda ambil, perbarui, atau hapus satu per satu dan kueri berdasarkan kolom:
DocStore. Tambahkan indeks untuk kolom yang Anda gunakan sebagai filter. - Peristiwa atau versi yang sebagian besar ditambahkan dan dibaca kembali secara berurutan atau berdasarkan jendela waktu:
SegmentedLog. - Pekerjaan yang diserahkan produsen ke proses worker:
Queue. Pengambilan dan penyelesaian aman untuk banyak proses, sedangkanclaimMany()/completeMany()meratakan biaya lock dan fsync. - Join, pencarian, atau pelaporan atas koleksi apa pun: tambahkan mirror SQL. File tetap menjadi sumber kanonis; mirror adalah proyeksi yang dapat dibangun ulang di SQLite atau MySQL.
Mesin dapat dikombinasikan: semuanya hanya berbagi direktori root, sehingga satu aplikasi dapat menyimpan konten di DocStore, jejak audit di SegmentedLog, dan pekerjaan latar belakang di Queue pada root penyimpanan yang sama.
DocStore
DocStore digunakan untuk pembacaan langsung dan pemindaian sederhana atas catatan persisten. Setiap catatan ditulis ke satu file JSONC:
$store = new Storh\DocStore($root, 'articles');
$record = $store->put(['slug' => 'hello', 'published' => true]);
$same = $store->get($record->id());
File catatan dibagi ke beberapa shard berdasarkan UUID karakter terakhir agar UUIDv7 lonjakan penulisan tersebar di berbagai direktori:
articles/data/2d/018bcfe5-6800-7000-8000-2d5dba6274da.jsonc
SegmentedLog
SegmentedLog digunakan untuk catatan yang sering ditambahkan, pembacaan dengan cursor, dan pembacaan rentang waktu. Catatan ditulis ke segmen aktif, satu baris per catatan dalam format <byte-length>\t<xxh32>\t<json> (lihat Atomisitas). File segmen menggunakan ekstensi .ndjson, tetapi prefiks panjang dan checksum membuatnya tidak dapat dibaca oleh alat NDJSON biasa; baca kembali catatan dengan stream() atau query builder. Segmen penuh bergulir menjadi segmen tersegel dengan indeks sparse.
$events = new Storh\SegmentedLog($root, 'events');
$events->put(['type' => 'user.created']);
$events->compact();
Antrean
Queue digunakan untuk antrean pekerjaan persisten berthroughput tinggi. Enqueue, claim, complete, requeue, dan purge menulis peristiwa append-only ke queue.log; status antrean diputar ulang ke memori saat antrean dibuka. Metode batch meratakan biaya lock dan flush untuk banyak pekerjaan. Log bertambah setiap kali ada peristiwa; stats() melaporkan ukuran byte saat ini.
$queue = new Storh\Queue($root, 'mail');
$queue->enqueue(['to' => 'person@example.test']);
$job = $queue->claim();
Persistensi dan konkurensi
storh menerbitkan penulisan file dengan penggantian nama atomik di dalam direktori target. Saat dibuka kembali, repair() menghapus file sementara terbengkalai milik proses yang sudah berhenti, sambil membiarkan file sementara penulis yang masih aktif. Penanda penulis membuat pemeriksaan ini berlangsung dalam waktu konstan, sehingga pembukaan penyimpanan menyapu koleksi hanya setelah crash.
SegmentedLog dan Queue menulis baris log dengan panjang dan checksum sebagai pengaman. Saat dibuka kembali atau diperbaiki, ekor yang terpotong dipangkas hingga peristiwa terakhir yang dikomit, lalu status dalam memori dibangun ulang dari isi log persisten. Penulisan log dan antrean diserialisasi dengan lock sistem file.
Mutasi DocStore diserialisasi dengan lock tulis tingkat koleksi, sehingga file catatan dan indeks sekunder diperbarui sebagai satu batas konsistensi lintas proses. Penulisan serentak ke ID catatan yang berbeda aman dengan asumsi penggantian nama atomik sistem file yang sama. Penulisan serentak ke ID yang sama mengikuti aturan penggantian nama terakhir yang menang.
storh melakukan flush dan fsync pada handle file sebelum penggantian nama atau penyelesaian append, serta berupaya melakukan fsync pada direktori induk setelah penggantian nama atomik. Persistensi saat listrik padam tetap bergantung pada sistem file dan opsi mount yang mendukung sinkronisasi tersebut.