synology_apm_repo.sdk.storage.recording module¶
RecordingStore/ReplayStore capture real ObjectStore traffic
into a small, committable fixture, then replay it later without touching
any real sample data.
The problem this solves: integration tests need real, production-shaped
bytes to be meaningful, but the real sample repositories are far too large
to live in CI. Wrapping ObjectStore’s four narrow byte-oriented
methods to record every call/result pair is cheap, and the resulting
fixture for one realistic scenario is typically a few hundred KB to a
couple MB uncompressed — small enough to commit alongside the test it
supports: record once against a real sample with RecordingStore, dump
it to JSON, then replay it forever after in CI via ReplayStore, with
zero real I/O. Fixtures are committed gzip-compressed
(tests/fixtures/*.json.gz) via write_fixture_text; load_fixture_text/
ReplayStore.from_path decompress transparently on read.
TracingStore below reuses the same mechanism for the CLI’s --trace
flag — observing every ObjectStore.read() call is the same capability
whether the goal is a test fixture or showing a user why a command was
slow.
- synology_apm_repo.sdk.storage.recording.load_fixture_text(path)¶
Read a fixture, transparently gzip-decompressing.
- Parameters:
path (Path) – Fixture file to read. Read as plain text unless it ends in
.gz— this project’s on-disk convention for a committedtests/fixtures/*.json.gzcassette.
- synology_apm_repo.sdk.storage.recording.write_fixture_text(path, text)¶
Write fixture text, gzip-compressing when
pathends in.gz.
- class synology_apm_repo.sdk.storage.recording.RecordingStore(backing)¶
Bases:
objectWraps a real
ObjectStoreand records every call/result pair for laterdump.- async read(path, offset=0, length=None)¶
- async size(path)¶
- async exists(path)¶
- async listdir(path)¶
- async aclose()¶
Delegates to
_InstrumentedStore.aclose()so a realS3Store/AzureStorerecorded against (--record-against=profile:<name>) still gets itsaiohttpconnector closed once recording is done.
- dump()¶
Serialize everything recorded so far to a JSON string suitable for committing as a test fixture (binary read results are base64-encoded).
- class synology_apm_repo.sdk.storage.recording.ReplayStore(fixture_json)¶
Bases:
objectAnswers
ObjectStorecalls purely from aRecordingStore.dumpfixture — no real backing store, no I/O.- Raises:
NotFoundError – For any call that was not recorded, so a fixture’s coverage gaps surface immediately as a test failure rather than silently returning wrong data (this is why
exists()also raises rather than defaulting toFalsefor an unrecorded path — a “does not exist” result must have been recorded).
- classmethod from_path(path)¶
Construct from a fixture file, transparently gzip-decompressing a
.json.gzpath (seeload_fixture_text).
- async read(path, offset=0, length=None)¶
- async size(path)¶
- async exists(path)¶
- async listdir(path)¶
- class synology_apm_repo.sdk.storage.recording.TraceEvent(method, path, offset=0, length=None, result_length=None, elapsed=0.0)¶
Bases:
objectOne
ObjectStorecall, for the--traceCLI flag.Unlike
RecordingStore, nothing is buffered — a real--tracerun against a real repository can touch millions of chunks, soTracingStorestreams one event per call straight to a callback instead.- Variables:
method (str) –
"read","size","exists", or"listdir".path (str) – Store-relative path the call targeted.
offset (int) –
read’s byte offset;0for every other method.length (int | None) –
read’s requested length;Nonefor every other method.result_length (int | None) – Bytes actually returned (
read) or entries listed (listdir);Noneforsize/exists, which report a plain value rather than a count.elapsed (float) – Wall-clock seconds the call took.
- class synology_apm_repo.sdk.storage.recording.TracingStore(backing, on_event)¶
Bases:
objectWraps a real
ObjectStore, callingon_eventonce per call with aTraceEvent— the same “wrap the four narrow methods” mechanismRecordingStoreabove uses. Every call is forwarded tobackingand its result returned/raised unchanged.- property backing: ObjectStore¶
The real store this instance forwards to – lets a caller tracking store identity (
Session.close_repo()) recognize two separateTracingStorewraps of the same backing connector as one shared resource, not two.
- async read(path, offset=0, length=None)¶
- async size(path)¶
- async exists(path)¶
- async listdir(path)¶
- async aclose()¶
Delegates to
_InstrumentedStore.aclose()so a realS3Store/AzureStorewrapped for--trace(or by this project’s own smoke tooling, which always traces) still gets itsaiohttpconnector closed bySession.close().