mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-06-22 13:01:14 +00:00
[AZ-308] c6 CacheBudgetEnforcer: 10 GB hard cap + LRU sweep
CacheBudgetEnforcer.reserve_headroom(needed_bytes) returns immediately when total_disk_bytes() + needed_bytes <= budget, otherwise iterates lru_candidates in eviction_batch_size batches, deletes via delete_tile, emits one INFO log per evicted tile (c6.evicted) and one FDR record per eviction batch (c6.eviction_batch, evicted_tile_ids capped to 5). Raises CacheBudgetExhaustedError AFTER a full sweep if the budget cannot be met. BudgetEnforcedTileStore decorates a TileStore so the policy stays separable from PostgresFilesystemStore. Composition root in storage_factory.build_tile_store wires the wrapper unconditionally. PostgresFilesystemStore now accepts lru_clock: Clock | None = None; when set, read_tile_pixels calls record_lru_access(tile_id, now) so eviction picks the right LRU candidates. Production wiring injects WallClock(); AZ-305 unit tests still construct without the clock and keep their pass-through semantics. Contract tile_store.md bumped to v1.1.0 to add CacheBudgetExhaustedError to the TileCacheError family; shared FDR schema bumped to v1.3.0 for the new c6.eviction_batch kind. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -71,14 +71,26 @@ def build_tile_store(config: Config) -> TileStore:
|
||||
invoked via ``PostgresFilesystemStore.from_config(config)`` which
|
||||
wires the ``ConnectionPool`` / ``FdrClient`` / logger / static
|
||||
helper dependencies from the config block.
|
||||
|
||||
AZ-308: the returned :class:`TileStore` is wrapped in a
|
||||
:class:`BudgetEnforcedTileStore` so every ``write_tile`` first
|
||||
reserves head-room against the configured
|
||||
``lru_eviction_threshold_bytes`` budget (RESTRICT-SAT-2). The
|
||||
wrapper is transparent for read-side consumers.
|
||||
"""
|
||||
block = _c6_config(config)
|
||||
runtime = block.store_runtime
|
||||
if runtime == "postgres_filesystem":
|
||||
try:
|
||||
from gps_denied_onboard.components.c6_tile_cache.cache_budget_enforcer import (
|
||||
BudgetEnforcedTileStore,
|
||||
CacheBudgetEnforcer,
|
||||
)
|
||||
from gps_denied_onboard.components.c6_tile_cache.postgres_filesystem_store import (
|
||||
PostgresFilesystemStore,
|
||||
)
|
||||
from gps_denied_onboard.fdr_client.client import make_fdr_client
|
||||
from gps_denied_onboard.logging import get_logger
|
||||
except ModuleNotFoundError as exc:
|
||||
raise RuntimeNotAvailableError(
|
||||
f"TileStore runtime {runtime!r} is configured but its "
|
||||
@@ -86,7 +98,15 @@ def build_tile_store(config: Config) -> TileStore:
|
||||
"'c6_tile_cache.postgres_filesystem_store' has not been "
|
||||
"built into this binary yet (AZ-305 pending)."
|
||||
) from exc
|
||||
return PostgresFilesystemStore.from_config(config)
|
||||
store = PostgresFilesystemStore.from_config(config)
|
||||
enforcer = CacheBudgetEnforcer(
|
||||
store=store,
|
||||
fdr_client=make_fdr_client("c6_tile_cache.budget", config),
|
||||
logger=get_logger("c6_tile_cache.budget"),
|
||||
budget_bytes=block.lru_eviction_threshold_bytes,
|
||||
eviction_batch_size=block.eviction_batch_size,
|
||||
)
|
||||
return BudgetEnforcedTileStore(wrapped=store, enforcer=enforcer)
|
||||
raise RuntimeNotAvailableError(
|
||||
f"TileStore runtime {runtime!r} is not buildable in this binary."
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user