webstation-broker
DeveloperPython referenceemulatorsemulators.extraction_cache

emulators.extraction_cache.ExtractionCache

A per-instance, opt-in archive/pkg extraction cache.

A per-instance, opt-in archive/pkg extraction cache.

One instance owns one cache directory tree and one lock; no two instances may ever own or nest the same directory (a convention this class does not itself enforce).

Functions

func__init__(self, name, cache_dir, enabled, max_gb, find_boot_target, *, budget=None, stage=None, phase_name=lambda rom: 'extracting_archive', on_evict=None, expansion_factor=lambda: 4.0, extract_timeout=lambda: 1800.0, lock_wait=lambda: 120.0, missing_target_error='held no bootable target') -> None

Initialize the extraction cache with callables for all configuration.

All configuration parameters are stored as callables, never snapshotted, so consumer modules can monkeypatch their module-level config at test time and this instance will read the current values on each call.

paramself
paramnamestr

The cache name, for logging and identification.

paramcache_dirCallable[[], Path]

Callable returning the cache root directory.

paramenabledCallable[[], bool]

Callable returning True if the cache is enabled.

parammax_gbCallable[[], float]

Callable returning the maximum cache size in GB.

paramfind_boot_targetCallable[[Path], Optional[Path]]

Callable taking a Path and returning the bootable target inside it, or None.

parambudgetOptional[Callable[[Path], tuple[int, int]]]
= None

Optional callable for cache budget calculation.

paramstageOptional[Callable[[Path, Path, Path, Emulator, int], None]]
= None

Optional callable for custom extraction staging.

paramphase_nameCallable[[Path], str]
= lambda rom: 'extracting_archive'

Callable returning the phase name for a ROM.

paramon_evictOptional[Callable[[Path], None]]
= None

Optional callable run when evicting a cache entry.

paramexpansion_factorCallable[[], float]
= lambda: 4.0

Callable returning the expected extraction expansion factor.

paramextract_timeoutCallable[[], float]
= lambda: 1800.0

Callable returning extraction timeout in seconds.

paramlock_waitOptional[Callable[[], float]]
= lambda: 120.0

Optional callable returning lock wait timeout in seconds.

parammissing_target_errorstr
= 'held no bootable target'

Error message when no bootable target is found.

Returns

None
funcroot(self) -> Path

The configured cache directory, read live from the cache_dir callable.

paramself

Returns

pathlib.Path
funcentry_dir(self, rom) -> Optional[Path]

The cache entry an earlier extract of rom left, without extracting anything.

paramself
paramromPath

The archive or package.

Returns

typing.Optional

The entry's directory, or None when rom has not been extracted

func_cache_size_bytes(self) -> int

Sum the sizes of all cache entries, or zero if the cache dir doesn't exist yet.

paramself

Returns

int

The total size in bytes of all files in all cache entries under root(), or 0 if root() is not a directory.

func_evict_lru(self, needed_bytes, keep) -> None

Evict least-recently-used cache entries until needed_bytes fits within max_gb.

paramself
paramneeded_bytesint

Additional bytes that must fit under the cache cap.

paramkeepstr

The cache key currently being (re-)extracted, so a stale entry for it already removed by the caller is never chosen.

Returns

None
func_require_room(self, peak_bytes, kept_bytes, rom_name) -> None

Refuse an extraction that cannot fit before any of it is written.

Two different figures cover two different ceilings: the cache cap counts only what survives (kept_bytes), while the free-space guard counts what is on disk at the extraction's worst moment (peak_bytes), which can exceed what is kept when a consumer's staging needs scratch space alongside its final output.

Raises

  • RuntimeError: If the cache cap or the filesystem cannot hold it.
paramself
parampeak_bytesint

Bytes on disk at the height of the extraction.

paramkept_bytesint

Bytes the finished extraction leaves in the cache.

paramrom_namestr

The ROM being extracted, named in the error.

Returns

None
func_locked(self, what) -> Iterator[None]

Hold this instance's lock for the block.

Blocks with no timeout when lock_wait is None; otherwise gives up and raises after lock_wait() seconds.

Raises

  • RuntimeError: When a bounded lock_wait elapses before the lock is free.
paramself
paramwhatstr

The operation waiting for the lock, named in the log and the error.

Returns

typing.Iterator[None]
func_clear_scratch(self) -> None

Remove every staged extraction under the scratch dir. Callers must hold _locked.

The lock is what makes this safe: no extraction can be mid-flight while it is held, so anything still sitting here was orphaned by a process that died.

paramself

Returns

None
funcsweep_stale_extractions(self) -> None

Remove extraction scratch dirs orphaned by a crashed broker process.

Call once at broker startup: the only other caller is an extraction, which a library of already-extracted (or never-archived) titles may never run again.

paramself

Returns

None
func_default_stage(self, archive, staged, scratch, emulator, kept_bytes) -> None

The default stage: extract archive directly into staged.

paramself
paramarchivePath
paramstagedPath
paramscratchPath
paramemulatorEmulator
paramkept_bytesint

Returns

None
func_default_budget(self, rom) -> tuple[int, int]

The default budget: the archive's own listed size, or a compressed-size fallback.

paramself
paramromPath

Returns

tuple[int, int]
funcextract(self, rom, emulator) -> Path

Get rom booting from the cache, extracting it if not already cached.

Reuses a prior extraction keyed by _cache_key when one already holds a bootable target. rom is staged under a scratch dir and only renamed to the persistent game_dir once a boot target is confirmed, so game_dir either does not exist or holds a complete extraction.

Holds this instance's lock for the whole call: eviction, extraction, and the boot-target lookup all touch the same cache tree, so a second call racing in here must wait rather than potentially evicting the directory this one is mid-extracting into or about to boot from.

Raises

  • RuntimeError: If rom cannot be read to key it, the extraction cannot fit in the cache or on the disk, stage fails, the extraction holds no boot target, or the finished extraction cannot be moved to its cache key.
  • OSError: If the cache dir or a scratch dir cannot be created at all.
paramself
paramromPath

The archive or package to extract.

paramemulatorEmulator

The launching emulator; emulator.extraction_phase is set while this runs, cleared again before returning or raising.

Returns

pathlib.Path

On this page