diff --git a/services/dcs/src/dcs/core/data_repository.py b/services/dcs/src/dcs/core/data_repository.py index 3cceb97..4dc3573 100644 --- a/services/dcs/src/dcs/core/data_repository.py +++ b/services/dcs/src/dcs/core/data_repository.py @@ -28,7 +28,7 @@ S3ObjectStoragesConfig, ) from hexkit.protocols.objstorage import ObjectStorageProtocol -from pydantic import Field, PositiveInt, field_validator +from pydantic import Field, PositiveInt, field_validator, model_validator from pydantic_settings import BaseSettings from dcs.adapters.outbound.http import exceptions @@ -56,21 +56,21 @@ class DataRepositoryConfig(BaseSettings): examples=["drs://localhost:8080/"], ) staging_speed: int = Field( - 100, + default=100, description="When trying to access a DRS object that is not yet in the outbox," + " assume that this many megabytes can be staged per second.", title="Staging speed in MB/s", examples=[100, 500], ) retry_after_min: int = Field( - 5, + default=5, description="When trying to access a DRS object that is not yet in the outbox," + " wait at least this number of seconds before trying again.", title="Minimum retry time in seconds when staging", examples=[5, 10], ) retry_after_max: int = Field( - 300, + default=300, description="When trying to access a DRS object that is not yet in the outbox," + " wait at most this number of seconds before trying again.", title="Maximum retry time in seconds when staging", @@ -98,7 +98,7 @@ class DataRepositoryConfig(BaseSettings): examples=[5, 10], ) cache_timeout: int = Field( - 7, + default=7, description="Time in days since last access after which a file present in the " + "outbox should be unstaged and has to be requested from permanent storage again " + "for the next request.", @@ -118,6 +118,19 @@ def check_server_uri(cls, value: str): return value + @model_validator(mode="after") + def check_url_expiration_buffer(self): + """Check that the buffer is less than the expiration time.""" + value = self.url_expiration_buffer + if value >= self.presigned_url_expires_after: + message = ( + "url_expiration_buffer must be less than presigned_url_expires_after" + + f", got: {value} (should be less than" + + f" {self.presigned_url_expires_after})" + ) + raise ValueError(message) + return self + class DataRepository(DataRepositoryPort): """A service that manages a registry of DRS objects.""" diff --git a/services/dcs/tests_dcs/test_edge_cases.py b/services/dcs/tests_dcs/test_edge_cases.py index eeee5cf..0f31e1b 100644 --- a/services/dcs/tests_dcs/test_edge_cases.py +++ b/services/dcs/tests_dcs/test_edge_cases.py @@ -29,6 +29,7 @@ from dcs.config import Config from dcs.core import models +from dcs.core.data_repository import DataRepositoryConfig from dcs.inject import prepare_rest_app from dcs.ports.outbound.dao import DrsObjectDaoPort from tests_dcs.fixtures.joint import EXAMPLE_FILE, JointFixture, PopulatedFixture @@ -239,3 +240,21 @@ async def test_cache_headers( assert "Cache-Control" in response.headers assert response.headers["Cache-Control"] == f"max-age={expected_url_max_age}" + + +async def test_cache_param_validation(): + """Test that the http cache-related config parameters are validated correctly""" + with pytest.raises(ValueError): + DataRepositoryConfig( + drs_server_uri="", + ekss_base_url="", + presigned_url_expires_after=0, + url_expiration_buffer=10, + ) + with pytest.raises(ValueError): + DataRepositoryConfig( + drs_server_uri="", + ekss_base_url="", + presigned_url_expires_after=10, + url_expiration_buffer=10, + )