Zrkadlo SQL
SqlMirror presúva kolekcie storh do tabuliek SQLite alebo MySQL, aby ste mohli
v SQL spúšťať spájanie tabuliek, zoradenie naprieč tabuľkami, vyhľadávanie podreťazcov a vytvárať reporty, pričom súbory zostávajú v kanonickom formáte. Predstavte si ho ako sekundárny index, ktorý je zároveň databázou: zrkadlo je odvodené, možno ho zahodiť a kedykoľvek znova vytvoriť.
ext-pdo s ovládačom sqlite alebo mysql je potrebné iba pri jeho použití; základný balík zostáva bez závislostí.
Nastavenie
use Storh\DocStore;
use Storh\Schema;
use Storh\SqlMirror;
$schema = Schema::collection('pages')
->string('slug')->unique()
->string('kind')->index()
->int('publishedAt')->range();
$pages = new DocStore($root, 'pages', schema: $schema);
$events = new Storh\SegmentedLog($root, 'events');
$mirror = new SqlMirror(new PDO('sqlite:' . $root . '/mirror.db'), 'app_');
$mirror->collection($pages, 'pages', $schema);
$mirror->collection($events, 'events');
$mirror->install();
$mirror->push();
Možno zrkadliť oba moduly: kolekcie DocStore aj streamy SegmentedLog (presúvajú sa iba živé záznamy). Odovzdanie objektu Schema je voliteľné a nezávislé od úložiska: deklarované polia string/int/float/bool sa zmenia na typované indexované stĺpce; všetko ostatné zostáva vyhľadateľné v stĺpci data JSON. Polia mixed nemožno označiť príznakom indexovania.
Pripojenia
Konštruktor prijíma objekt pripojenia PDO (ovládač sqlite alebo mysql, rozpoznaný automaticky), objekt pripojenia mysqli alebo ľubovoľnú implementáciu SqlMirrorConnection:
$mirror = new SqlMirror(new PDO('sqlite:' . $root . '/mirror.db'));
$mirror = new SqlMirror(new PDO('mysql:host=127.0.0.1;dbname=app;charset=utf8mb4', $user, $password));
$mirror = new SqlMirror(new mysqli('127.0.0.1', $user, $password, 'app'), 'wp_storh_');
Cesta mysqli funguje pri oboch režimoch hlásenia chýb mysqli, takže možno opätovne použiť existujúci objekt pripojenia z hostiteľskej aplikácie, napríklad WordPress $wpdb->dbh, bez úprav. Správanie je vo všetkých ovládačoch rovnaké; pri zlyhaní presunu sa transakcia kolekcie v každom z nich vráti späť.
Každá tabuľka obsahuje id (primárny kľúč), hash (riadi priebežné presuny), typované stĺpce a data (úplný záznam JSON).
Synchronizácia
$mirror->push(); // reconcile: insert, update, delete as needed
$mirror->push('pages'); // reconcile a single collection
$mirror->flush('pages', $ids); // push or remove just these ids
$mirror->pull(); // write mirror rows back into the store
$mirror->verify(); // report missing, stale, and orphaned rows
$mirror->rebuild(); // clear all rows and push from scratch
$mirror->uninstall(); // drop the mirror tables
push() porovnáva kontrolné súčty záznamov so zrkadlom a zapisuje každú kolekciu v rámci jednej transakcie, takže po páde alebo zlyhaní presunu nikdy nezostane dávka spracovaná iba čiastočne. Spracovanie nezmenených záznamov stojí jedno SELECT a prechod cez záznamy. Pravidelný push() (napríklad pri každom cykle cron) udržiava zrkadlo aktuálne; ak čitatelia potrebujú vidieť vlastné zápisy v zrkadle, zavolajte flush() s ID, ktoré ste zapísali počas požiadavky.
Dotazovanie
Dotazujte zrkadlo pomocou obyčajného SQL. table() vráti názov zrkadlenej tabuľky:
$pdo->query(
'SELECT p.slug, COUNT(*) AS sales
FROM ' . $mirror->table('purchases') . ' o
INNER JOIN ' . $mirror->table('products') . ' p ON p.id = o.product_id
GROUP BY p.slug
ORDER BY sales DESC'
);
Prenos späť do súborov
pull() číta riadky zrkadla a v poradí podľa ID ich zapisuje do registrovaného úložiska. Podporuje dva postupy:
- Obnovenie: súbory sú preč, ale zrkadlo zostalo. Zaregistrujte nové úložisko s rovnakým názvom kolekcie a načítajte údaje.
- Naplnenie: riadky vložené externými nástrojmi do tabuľky zrkadla sa zmenia na záznamy storh. Riadky musia obsahovať platné identifikátory UUIDv7 a objekt v stĺpci
data; typované stĺpce sa pri načítaní ignorujú, pretožedatapredstavuje celý záznam.
$restored = new Storh\DocStore($root, 'pages');
$mirror = new SqlMirror($pdo);
$mirror->collection($restored, 'pages');
$mirror->pull(); // ['written' => n, 'unchanged' => m]
Zápisy načítané zo zrkadla prechádzajú bežným mechanizmom úložiska, takže sa uplatňuje validácia schémy aj jedinečné indexy a každý záznam sa zapisuje trvalo. pull() nikdy neodstraňuje lokálne záznamy a záznamy, ktorých údaje sa už zhodujú s riadkom v zrkadle, preskočí. Po vložení riadkov naplnených ručne raz spustite push(): prepíše tieto riadky v kanonickom tvare, aby sa ich hashe zosúladili.
Zmluva a obmedzenia
- Súbory sú kanonické. Zrkadlo je výstup určený len na čítanie; všetko, čo sa doň ručne zapíše, prepíše alebo odstráni nasledujúce
push(). - Jedinečné stĺpce v zrkadle slúžia ako poistka, nie ako vynucovanie pri zápise: duplicita povolená súbormi sa prejaví ako neúspešné (a úplne vrátené) odoslanie. Na vynucovanie pri zápise použite jedinečné indexy storh.
- Zrkadlo zaostáva za súbormi až o jeden interval odosielania, s výnimkou identifikátorov, ktoré výslovne
flush(). - Zrkadlenie nepridáva transakcie do samotného storh. Atómové zápisy viacerých záznamov zostávajú úlohou pre skutočnú databázu, ktorá slúži ako zdroj pravdy.
- Zmeny schémy sa uplatňujú odstránením a opätovnou inštaláciou zrkadla:
uninstall(),install(),push().