PdoCassetteStore
A PDO-backed ListableCassetteStoreInterface: a pod’s filesystem does not survive a restart/eviction, so a team without an object-store backend keeps cassettes in the database it already has instead.
Portable across PostgreSQL and SQLite only (INSERT ... ON CONFLICT, matching PdoRateLimiterStorage’s and queue-db’s own documented scope for this class of hand-rolled SQL) — MySQL/MariaDB support would need ON DUPLICATE KEY UPDATE instead and is not implemented. The gzip-encoded cassette payload CassetteCodec produces is not valid UTF-8, so it is base64-encoded into a plain TEXT column rather than a driver-specific BYTEA/BLOB type — the same portability trick PdoRateLimiterStorage::save() already uses for its own binary-ish payload, needed because a single CREATE TABLE string cannot name a binary column type both engines accept.
recorded_at/route/status/trigger_reason are extracted from the cassette at write time into their own indexed-by-nothing-yet columns — not because a query here uses them (slugs() still returns every id, and cassette:list/cassette:prune decode-and-filter in PHP exactly as they do against FileCassetteStore, so both stores share one filtering implementation) but so the raw table is legible and directly queryable by hand (SELECT * FROM quiote_cassettes WHERE status >= 500) without decoding a payload column first.
Schema (see PdoCassetteStore::schema()): CREATE TABLE quiote_cassettes ( slug VARCHAR(64) PRIMARY KEY, raw_id VARCHAR(255) NOT NULL, recorded_at VARCHAR(32) NULL, route VARCHAR(255) NULL, status INTEGER NULL, trigger_reason VARCHAR(32) NULL, payload TEXT NOT NULL );
Synopsis
Section titled “Synopsis”final readonly class PdoCassetteStore implements ListableCassetteStoreInterface
| Implements | ListableCassetteStoreInterface |
| Source | PdoCassetteStore.php |
Constructor
Section titled “Constructor”__construct()
Section titled “__construct()”public function __construct(PDO $pdo, string $table = 'quiote_cassettes', CassetteCodec $codec = new CassetteCodec(…)): mixed
| Parameter | Type | Description |
|---|---|---|
$pdo | PDO | |
$table | string | |
$codec | CassetteCodec |
Returns mixed
Methods
Section titled “Methods”| Method | Description |
|---|---|
delete(CassetteId $id): void | Removes the cassette at $id. |
get(CassetteId $id): ?Cassette | Null when no cassette is stored under this id. |
has(CassetteId $id): bool | |
put(CassetteId $id, Cassette $cassette): void | |
schema(string $table = 'quiote_cassettes'): string | DDL to create the backing table (PostgreSQL / SQLite compatible). |
slugs(): list<string> | Every cassette slug in the table. |
delete()
Section titled “delete()”public function delete(CassetteId $id): void
Removes the cassette at $id.
Best-effort: an id that does not exist is not an error.
| Parameter | Type | Description |
|---|---|---|
$id | CassetteId |
| Throws | When |
|---|---|
StorageException | if the delete does not succeed. |
public function get(CassetteId $id): ?Cassette
Null when no cassette is stored under this id.
| Parameter | Type | Description |
|---|---|---|
$id | CassetteId |
Returns ?Cassette
| Throws | When |
|---|---|
StorageException | if the read does not succeed. |
public function has(CassetteId $id): bool
| Parameter | Type | Description |
|---|---|---|
$id | CassetteId |
Returns bool
| Throws | When |
|---|---|
StorageException | if the read does not succeed. |
public function put(CassetteId $id, Cassette $cassette): void
| Parameter | Type | Description |
|---|---|---|
$id | CassetteId | |
$cassette | Cassette |
| Throws | When |
|---|---|
StorageException | if the write does not succeed. |
schema()
Section titled “schema()”public static function schema(string $table = 'quiote_cassettes'): string
DDL to create the backing table (PostgreSQL / SQLite compatible).
| Parameter | Type | Description |
|---|---|---|
$table | string |
Returns string
slugs()
Section titled “slugs()”public function slugs(): list<string>
Every cassette slug in the table.
A failed query raises rather than returning an empty list. Reporting an error as “the store * is empty” is the worst available answer for the two callers this has: cassette:list would print “No cassettes found” for a table it could not read, and cassette:prune would decide there was nothing to prune.
Returns list``<``string``>
| Throws | When |
|---|---|
StorageException | if the listing does not succeed. |