Files
wehub-resource-sync bcbd1bdb22
Integ / changes (push) Has been skipped
Pre-commit / pre-commit (push) Failing after 1s
CLI exit codes / changes (push) Has been skipped
Test (Install) / changes (push) Has been skipped
Test (Python) / changes (push) Has been skipped
Test (TypeScript) / changes (push) Has been skipped
CLI exit codes / cli-gate (push) Has been cancelled
Test (Install) / test-install-gate (push) Has been cancelled
Integ / integ-gate (push) Has been cancelled
Test (Python) / test-python-gate (push) Has been cancelled
Test (TypeScript) / test-typescript-gate (push) Has been cancelled
Test (Install) / python-minimal (3.12) (push) Has been cancelled
Test (Install) / python-minimal (3.11) (push) Has been cancelled
Test (Install) / python-extra (agno, mirage.agents.agno) (push) Has been cancelled
Test (Install) / python-extra (chroma, mirage.resource.chroma) (push) Has been cancelled
Test (Install) / python-extra (pdf, mirage.core.filetype.pdf) (push) Has been cancelled
Integ / integ (push) Has been cancelled
Integ / integ-database (push) Has been cancelled
Integ / integ-database-ts (push) Has been cancelled
Integ / integ-data (push) Has been cancelled
Integ / integ-ssh (push) Has been cancelled
Integ / integ-ssh-ts (push) Has been cancelled
Test (Python) / audit (push) Has been cancelled
Test (TypeScript) / test (push) Has been cancelled
Test (TypeScript) / python-fs-shim (push) Has been cancelled
CLI exit codes / Python CLI (push) Has been cancelled
CLI exit codes / TypeScript CLI (push) Has been cancelled
CLI exit codes / Cross-language snapshot interop (push) Has been cancelled
Test (Python) / test (push) Has been cancelled
Test (Python) / import-isolation (deepagents, openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Python) / import-isolation (deepagents, pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Integ / integ-ts (push) Has been cancelled
Integ / integ-fuse (push) Has been cancelled
Test (Install) / python-extra (databricks, mirage.resource.databricks_volume) (push) Has been cancelled
Test (Install) / python-extra (deepagents, mirage.agents.langchain) (push) Has been cancelled
Test (Install) / python-extra (email, mirage.resource.email) (push) Has been cancelled
Test (Install) / python-extra (fuse, mirage.fuse.mount) (push) Has been cancelled
Test (Install) / python-extra (hdf5, mirage.core.filetype.hdf5) (push) Has been cancelled
Test (Install) / python-extra (hf, mirage.resource.hf_buckets) (push) Has been cancelled
Test (Install) / python-extra (lancedb, mirage.resource.lancedb) (push) Has been cancelled
Test (Install) / python-extra (langfuse, mirage.resource.langfuse) (push) Has been cancelled
Test (Install) / python-extra (mongodb, mirage.resource.mongodb) (push) Has been cancelled
Test (Install) / python-extra (nextcloud, mirage.resource.nextcloud) (push) Has been cancelled
Test (Install) / python-extra (openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Install) / python-extra (openhands, mirage.agents.openhands, 3.12) (push) Has been cancelled
Test (Install) / python-extra (parquet, mirage.core.filetype.parquet) (push) Has been cancelled
Test (Install) / python-extra (postgres, mirage.resource.postgres) (push) Has been cancelled
Test (Install) / python-extra (pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Test (Install) / python-extra (qdrant, mirage.resource.qdrant) (push) Has been cancelled
Test (Install) / python-extra (redis, mirage.resource.redis) (push) Has been cancelled
Test (Install) / python-extra (s3, mirage.resource.s3) (push) Has been cancelled
Test (Install) / python-extra (ssh, mirage.resource.ssh) (push) Has been cancelled
Test (Install) / ts-minimal (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:30:44 +08:00

111 lines
4.6 KiB
Python

# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
from mirage.cache.file.mixin import FileCacheMixin
from mirage.cache.index.store import IndexCacheStore
from mirage.types import PathSpec
class CacheManager:
"""Post-mutation cache coherence for one mount.
A backend mutation has two cache consequences: the file-cache entry
for the path is stale, and the parent directory listing in the
index cache (including negative knowledge that the path does not
exist) is stale. This class discharges both, synchronously, at the
mutation site: core backend mutators report through
``mirage.cache.context`` right where they already emit observe
records, so invalidation happens before the next command in a
pipeline runs instead of after the whole command tree.
"""
def __init__(self, file_cache: FileCacheMixin | None,
index: IndexCacheStore | None, prefix: str,
caches_reads: bool) -> None:
"""Args:
file_cache (FileCacheMixin | None): Workspace file cache
store; entries are keyed by mount-absolute path.
index (IndexCacheStore | None): The mount resource's index
cache; listings are keyed by mount-absolute path.
prefix (str): Mount prefix (e.g. "/data/").
caches_reads (bool): Whether the resource caches reads; the
file cache only holds paths for read-caching backends.
"""
self._file_cache = file_cache
self._index = index
self._prefix = prefix.rstrip("/")
self._caches_reads = caches_reads
def _virtual(self, path: str | PathSpec) -> str:
if isinstance(path, PathSpec):
path = path.mount_path
if not path.startswith("/"):
path = "/" + path
if self._prefix and not path.startswith(self._prefix):
return self._prefix + path
return path
async def cached_bytes(self, path: PathSpec) -> bytes | None:
"""Return cached bytes for ``path`` if present, else None.
Lookup only: never fetches from the backend. The single
read-cache check, called by the shared read-through wrappers
(``mirage.cache.read_through``) that every read command reads
through, so warm reads are served from the file cache without the
command knowing about it.
Args:
path (PathSpec): the path to look up.
"""
if not self._caches_reads or self._file_cache is None:
return None
virtual = self._virtual(path)
if await self._file_cache.exists(virtual):
return await self._file_cache.get(virtual)
return None
async def invalidate_after_write(self, path: str | PathSpec) -> None:
"""Invalidate caches after a write to ``path``.
Args:
path (str | PathSpec): Resource-relative path that was
written.
"""
virtual = self._virtual(path)
if self._caches_reads and self._file_cache is not None:
await self._file_cache.remove(virtual)
await self._invalidate_parent(virtual)
async def invalidate_after_unlink(self, path: str | PathSpec) -> None:
"""Invalidate caches after a deletion of ``path``.
Args:
path (str | PathSpec): Resource-relative path that was
removed.
"""
virtual = self._virtual(path)
if self._caches_reads and self._file_cache is not None:
await self._file_cache.remove(virtual)
if self._index is not None:
await self._index.invalidate_dir(virtual)
await self._index.invalidate_dir(virtual + "/")
await self._invalidate_parent(virtual)
async def _invalidate_parent(self, virtual: str) -> None:
if self._index is None:
return
parent = virtual.rsplit("/", 1)[0] or "/"
await self._index.invalidate_dir(parent)
await self._index.invalidate_dir(parent + "/")