Skip to content

Commit 7a41cd0

Browse files
author
Andrei Neagu
committed
added timedelta validator in everywhere it is required
1 parent 08fa3b2 commit 7a41cd0

File tree

9 files changed

+85
-17
lines changed

9 files changed

+85
-17
lines changed
Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,35 @@
11
import datetime
2+
import warnings
3+
from datetime import timedelta
24

3-
from pydantic import field_validator
4-
5-
6-
def _try_convert_str_to_float_or_return(
7-
v: datetime.timedelta | str | float,
8-
) -> datetime.timedelta | str | float:
9-
if isinstance(v, str):
10-
try:
11-
return float(v)
12-
except ValueError:
13-
# returns format like "1:00:00"
14-
return v
15-
return v
5+
from pydantic import TypeAdapter, field_validator
166

177

188
def timedelta_try_convert_str_to_float(field: str):
199
"""Transforms a float/int number into a valid datetime as it used to work in the past"""
10+
11+
def _try_convert_str_to_float_or_return(
12+
v: datetime.timedelta | str | float,
13+
) -> datetime.timedelta | str | float:
14+
if isinstance(v, str):
15+
try:
16+
converted_value = float(v)
17+
18+
iso8601_format = TypeAdapter(timedelta).dump_python(
19+
timedelta(seconds=converted_value), mode="json"
20+
)
21+
warnings.warn(
22+
f"{field}='{v}' -should be set to-> {field}='{iso8601_format}' (ISO8601 datetime format). "
23+
"Please also convert the value in the >>OPS REPOSITORY<<. "
24+
"For details: https://docs.pydantic.dev/1.10/usage/types/#datetime-types.",
25+
DeprecationWarning,
26+
stacklevel=8,
27+
)
28+
29+
return converted_value
30+
except ValueError:
31+
# returns format like "1:00:00"
32+
return v
33+
return v
34+
2035
return field_validator(field, mode="before")(_try_convert_str_to_float_or_return)

services/agent/src/simcore_service_agent/core/settings.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from datetime import timedelta
22

3+
from common_library.pydantic_validators import timedelta_try_convert_str_to_float
34
from models_library.basic_types import BootModeEnum, LogLevel
45
from pydantic import AliasChoices, AnyHttpUrl, Field, field_validator
56
from settings_library.base import BaseCustomSettings
@@ -51,14 +52,14 @@ class ApplicationSettings(BaseCustomSettings, MixinLoggingSettings):
5152
AGENT_VOLUMES_CLEANUP_INTERVAL: timedelta = Field(
5253
timedelta(minutes=1), description="interval for running volumes removal"
5354
)
54-
AGENT_VOLUMES_CLENUP_BOOK_KEEPING_INTERVAL: timedelta = Field(
55+
AGENT_VOLUMES_CLEANUP_BOOK_KEEPING_INTERVAL: timedelta = Field(
5556
timedelta(minutes=1),
5657
description=(
5758
"interval at which to scan for unsued volumes and keep track since "
5859
"they were detected as being unused"
5960
),
6061
)
61-
AGENT_VOLUMES_CLENUP_REMOVE_VOLUMES_INACTIVE_FOR: timedelta = Field(
62+
AGENT_VOLUMES_CLEANUP_REMOVE_VOLUMES_INACTIVE_FOR: timedelta = Field(
6263
timedelta(minutes=65),
6364
description=(
6465
"if a volume is unused for more than this interval it can be removed. "
@@ -75,6 +76,21 @@ class ApplicationSettings(BaseCustomSettings, MixinLoggingSettings):
7576
auto_default_from_env=True, description="settings for service/rabbitmq"
7677
)
7778

79+
_try_convert_agent_volumes_cleanup_interval = timedelta_try_convert_str_to_float(
80+
"AGENT_VOLUMES_CLEANUP_INTERVAL"
81+
)
82+
83+
_try_convert_agent_volumes_cleanup_book_keeping_interval = (
84+
timedelta_try_convert_str_to_float(
85+
"AGENT_VOLUMES_CLEANUP_BOOK_KEEPING_INTERVAL"
86+
)
87+
)
88+
_try_convert_agent_volumes_cleanup_remove_volumes_inactive_for = (
89+
timedelta_try_convert_str_to_float(
90+
"AGENT_VOLUMES_CLEANUP_REMOVE_VOLUMES_INACTIVE_FOR"
91+
)
92+
)
93+
7894
@field_validator("LOGLEVEL")
7995
@classmethod
8096
def valid_log_level(cls, value) -> LogLevel:

services/agent/src/simcore_service_agent/services/volumes_manager.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,9 @@ async def _on_startup() -> None:
174174

175175
volumes_manager = VolumesManager(
176176
app=app,
177-
book_keeping_interval=settings.AGENT_VOLUMES_CLENUP_BOOK_KEEPING_INTERVAL,
177+
book_keeping_interval=settings.AGENT_VOLUMES_CLEANUP_BOOK_KEEPING_INTERVAL,
178178
volume_cleanup_interval=settings.AGENT_VOLUMES_CLEANUP_INTERVAL,
179-
remove_volumes_inactive_for=settings.AGENT_VOLUMES_CLENUP_REMOVE_VOLUMES_INACTIVE_FOR.total_seconds(),
179+
remove_volumes_inactive_for=settings.AGENT_VOLUMES_CLEANUP_REMOVE_VOLUMES_INACTIVE_FOR.total_seconds(),
180180
)
181181
volumes_manager.set_to_app_state(app)
182182
await volumes_manager.setup()

services/director-v2/src/simcore_service_director_v2/core/dynamic_services_settings/scheduler.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from datetime import timedelta
22
from typing import Final
33

4+
from common_library.pydantic_validators import timedelta_try_convert_str_to_float
45
from models_library.projects_networks import DockerNetworkName
56
from pydantic import Field, NonNegativeInt, PositiveFloat
67
from settings_library.base import BaseCustomSettings
@@ -166,3 +167,12 @@ class DynamicServicesSchedulerSettings(BaseCustomSettings):
166167
DIRECTOR_V2_DYNAMIC_SIDECAR_SLEEP_AFTER_CONTAINER_REMOVAL: timedelta = Field(
167168
timedelta(0), description="time to sleep before removing a container"
168169
)
170+
171+
_try_convert_director_v2_dynamic_scheduler_interval = (
172+
timedelta_try_convert_str_to_float("DIRECTOR_V2_DYNAMIC_SCHEDULER_INTERVAL")
173+
)
174+
_try_convert_director_v2_dynamic_sidecar_sleep_after_container_removal = (
175+
timedelta_try_convert_str_to_float(
176+
"DIRECTOR_V2_DYNAMIC_SIDECAR_SLEEP_AFTER_CONTAINER_REMOVAL"
177+
)
178+
)

services/director-v2/src/simcore_service_director_v2/core/settings.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import datetime
66
from functools import cached_property
77

8+
from common_library.pydantic_validators import timedelta_try_convert_str_to_float
89
from models_library.basic_types import (
910
BootModeEnum,
1011
BuildTargetEnum,
@@ -234,3 +235,7 @@ class AppSettings(BaseCustomSettings, MixinLoggingSettings):
234235
def _validate_loglevel(cls, value: str) -> str:
235236
log_level: str = cls.validate_log_level(value)
236237
return log_level
238+
239+
_try_convert_service_tracking_heartbeat = timedelta_try_convert_str_to_float(
240+
"SERVICE_TRACKING_HEARTBEAT"
241+
)

services/dynamic-scheduler/src/simcore_service_dynamic_scheduler/core/settings.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import datetime
22
from functools import cached_property
33

4+
from common_library.pydantic_validators import timedelta_try_convert_str_to_float
45
from pydantic import Field, parse_obj_as, validator
56
from settings_library.application import BaseApplicationSettings
67
from settings_library.basic_types import LogLevel, VersionTag
@@ -53,6 +54,10 @@ def LOG_LEVEL(self): # noqa: N802
5354
def valid_log_level(cls, value: str) -> str:
5455
return cls.validate_log_level(value)
5556

57+
_try_convert_dynamic_scheduler_stop_service_timeout = (
58+
timedelta_try_convert_str_to_float("DYNAMIC_SCHEDULER_STOP_SERVICE_TIMEOUT")
59+
)
60+
5661

5762
class ApplicationSettings(_BaseApplicationSettings):
5863
"""Web app's environment variables

services/resource-usage-tracker/src/simcore_service_resource_usage_tracker/core/settings.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import datetime
22
from functools import cached_property
33

4+
from common_library.pydantic_validators import timedelta_try_convert_str_to_float
45
from models_library.basic_types import BootModeEnum
56
from pydantic import Field, PositiveInt, validator
67
from settings_library.base import BaseCustomSettings
@@ -114,3 +115,9 @@ class ApplicationSettings(MinimalApplicationSettings):
114115
RESOURCE_USAGE_TRACKER_TRACING: TracingSettings | None = Field(
115116
auto_default_from_env=True, description="settings for opentelemetry tracing"
116117
)
118+
119+
_try_convert_resource_usage_tracker_missed_heartbeat_interval_sec = (
120+
timedelta_try_convert_str_to_float(
121+
"RESOURCE_USAGE_TRACKER_MISSED_HEARTBEAT_INTERVAL_SEC"
122+
)
123+
)

services/web/server/src/simcore_service_webserver/projects/settings.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from datetime import timedelta
22

33
from aiohttp import web
4+
from common_library.pydantic_validators import timedelta_try_convert_str_to_float
45
from pydantic import ByteSize, Field, NonNegativeInt, parse_obj_as
56
from settings_library.base import BaseCustomSettings
67

@@ -23,6 +24,10 @@ class ProjectsSettings(BaseCustomSettings):
2324
description="interval after which services need to be idle in order to be considered inactive",
2425
)
2526

27+
_try_convert_projects_inactivity_interval = timedelta_try_convert_str_to_float(
28+
"PROJECTS_INACTIVITY_INTERVAL"
29+
)
30+
2631

2732
def get_plugin_settings(app: web.Application) -> ProjectsSettings:
2833
settings = app[APP_SETTINGS_KEY].WEBSERVER_PROJECTS

services/web/server/src/simcore_service_webserver/studies_dispatcher/settings.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import Any, ClassVar
33

44
from aiohttp import web
5+
from common_library.pydantic_validators import timedelta_try_convert_str_to_float
56
from pydantic import ByteSize, HttpUrl, parse_obj_as, validator
67
from pydantic.fields import Field
78
from servicelib.aiohttp.application_keys import APP_SETTINGS_KEY
@@ -50,6 +51,10 @@ def is_login_required(self):
5051
"""
5152
return not self.STUDIES_ACCESS_ANONYMOUS_ALLOWED
5253

54+
_try_convert_studies_guest_account_lifetime = timedelta_try_convert_str_to_float(
55+
"STUDIES_GUEST_ACCOUNT_LIFETIME"
56+
)
57+
5358
class Config:
5459
schema_extra: ClassVar[dict[str, Any]] = {
5560
"example": {

0 commit comments

Comments
 (0)