ObjectStoreCassetteStore
A ListableCassetteStoreInterface over any ListableObjectStoreClientInterface — Azure Blob, S3 or GCS.
A pod’s filesystem does not survive a restart/eviction/scale-down, which is disproportionately likely to be exactly when the interesting request happened.
put() writes to the deterministic, date-partitioned key CassetteKeyScheme derives from the cassette’s own recorded_at. get()/has()/delete()/slugs() take only a bare CassetteId or nothing at all — neither carries a date — so they cannot go straight to a key the way FileCassetteStore’s directory listing or PdoCassetteStore’s WHERE slug = ? can. Instead they probe backward hour by hour, from now, up to $lookbackHours (default a Docker-deployment-realistic 48h), checking each hour’s deterministic key with a cheap head() rather than listing. This makes the base CassetteStoreInterface contract honestly work with no further machinery — slower than an index-assisted lookup for an old cassette, but correct — and CassetteIndexInterface (an explicit key/date hint, or a Log Analytics query) is the faster path for exactly the case this probe is slow at, not a requirement for the store to function at all.
A stated, deliberate limitation, not a silent one: slugs() only enumerates the same $lookbackHours window get()/has()/delete() probe, not the object store’s entire history. A cassette older than that window exists and is still fetchable by key, but will not appear in cassette:list’s output.
Synopsis
Section titled “Synopsis”final class ObjectStoreCassetteStore implements ListableCassetteStoreInterface
| Implements | ListableCassetteStoreInterface |
| Source | ObjectStoreCassetteStore.php |
Constructor
Section titled “Constructor”__construct()
Section titled “__construct()”public function __construct(ListableObjectStoreClientInterface $client, CassetteKeyScheme $keyScheme, string $storeAlias, string $containerLabel, int $lookbackHours = 48, CassetteCodec $codec = new CassetteCodec(…), ClockInterface $clock = new SystemClock(…)): mixed
| Parameter | Type | Description |
|---|---|---|
$client | ListableObjectStoreClientInterface | |
$keyScheme | CassetteKeyScheme | |
$storeAlias | string | |
$containerLabel | string | |
$lookbackHours | int | |
$codec | CassetteCodec | |
$clock | ClockInterface |
Returns mixed
Methods
Section titled “Methods”| Method | Description |
|---|---|
delete(CassetteId $id): void | Deletes every copy, not just the newest. |
get(CassetteId $id): ?Cassette | Null when no cassette is stored under this id. |
has(CassetteId $id): bool | |
put(CassetteId $id, Cassette $cassette): void | |
slugs(): list<string> | Every slug the last $lookbackHours of hour-partitions hold — see this class’s own docblock for why that window, not the object store’s entire history. |
delete()
Section titled “delete()”public function delete(CassetteId $id): void
Deletes every copy, not just the newest.
put() keys by the cassette’s own recorded hour, so one slug can legitimately exist in several hour partitions — a re-recorded correlation id, or a cassette fetched from elsewhere and stored again. Stopping at the first hit meant cassette:prune reported a deletion while older copies survived indefinitely, which is the one thing a prune must not do.
| Parameter | Type | Description |
|---|---|---|
$id | CassetteId |
public function get(CassetteId $id): ?Cassette
Null when no cassette is stored under this id.
| Parameter | Type | Description |
|---|---|---|
$id | CassetteId |
Returns ?Cassette
public function has(CassetteId $id): bool
| Parameter | Type | Description |
|---|---|---|
$id | CassetteId |
Returns bool
public function put(CassetteId $id, Cassette $cassette): void
| Parameter | Type | Description |
|---|---|---|
$id | CassetteId | |
$cassette | Cassette |
slugs()
Section titled “slugs()”public function slugs(): list<string>
Every slug the last $lookbackHours of hour-partitions hold — see this class’s own docblock for why that window, not the object store’s entire history.
Returns list``<``string``>