Files
Tommaso Fontana b38832e251 Pypeline: move epoch to storage_provider
Move the epoch inside the storage_provider, this allows us to make the
storage_provider_factory to return an async context manager.
This way we can simplify the locking for the daemon, but forces the
CLI project commands to deal with async code.
2025-11-11 17:15:28 +01:00

123 lines
3.5 KiB
Python

#
# This file is distributed under the MIT License. See LICENSE.md for details.
#
from __future__ import annotations
from collections.abc import Buffer
from contextlib import asynccontextmanager
from datetime import datetime
from typing import AsyncGenerator, Iterable, Mapping
from revng import __version__ as revng_version
from revng.pypeline.container import ConfigurationId
from revng.pypeline.model import ModelPathSet
from revng.pypeline.object import ObjectID
from revng.pypeline.task.task import ObjectDependencies
from .file_provider import FileRequest
from .storage_provider import ContainerLocation, FileStorageEntry, InvalidatedObjects, ProjectID
from .storage_provider import ProjectMetadata, SavePointsRange, StorageProvider
from .storage_provider import StorageProviderFactory
from .util import compute_hash
class NullStorageProviderFactory(StorageProviderFactory):
def __init__(self, url: str):
assert url == "null://"
@classmethod
def scheme(cls) -> str:
return "null"
@asynccontextmanager
async def get(
self,
project_id: ProjectID | None,
token: str | None,
cache_dir: str | None,
) -> AsyncGenerator[StorageProvider]:
yield NullStorageProvider()
class NullStorageProvider(StorageProvider):
"""The /dev/null of storage providers. It stores nothing and caches nothing.
It just keeps track of the model, project ID, and last change time as those
are required by the interface.
"""
def __init__(self):
self.model = b""
self.last_change = datetime.now()
def has(
self,
location: ContainerLocation,
keys: Iterable[ObjectID],
) -> Iterable[ObjectID]:
return []
def get(
self,
location: ContainerLocation,
keys: Iterable[ObjectID],
) -> Mapping[ObjectID, bytes]:
assert not keys, "NullStorageProvider does not support get operation."
return {}
def add_dependencies(
self,
savepoint_range: SavePointsRange,
configuration_id: ConfigurationId,
deps: ObjectDependencies,
) -> None:
self.last_change = datetime.now()
def put(
self,
location: ContainerLocation,
values: Mapping[ObjectID, Buffer],
) -> None:
self.last_change = datetime.now()
def invalidate(self, invalidation_list: ModelPathSet) -> InvalidatedObjects:
self.last_change = datetime.now()
return {}
def get_epoch(self) -> int:
return 0
def get_model(self) -> tuple[bytes, int]:
return (self.model, self.get_epoch())
def set_model(self, new_model: bytes):
self.model = new_model
self.last_change = datetime.now()
return 0
def metadata(self) -> ProjectMetadata:
"""
Fetch metadata about the current project
"""
return ProjectMetadata(
last_change=self.last_change,
revng_version=revng_version,
)
def prune_objects(self):
"""
Prunes all the objects (except metadata) from storage
"""
def put_files_in_storage(self, files: list[FileStorageEntry]) -> list[str]:
result = []
for file in files:
if file.path is not None:
result.append(compute_hash(file.path))
elif file.contents is not None:
result.append(compute_hash(file.contents))
return result
def get_files_from_storage(self, requests: list[FileRequest]) -> dict[str, bytes]:
raise ValueError("Unsupported")