Skip to content

Commit fc054d6

Browse files
GitHKAndrei Neagumergify[bot]
authored
🎨 add Postgres connection to dynamic-scheduler (#7600)
Co-authored-by: Andrei Neagu <[email protected]> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent a8f88d6 commit fc054d6

29 files changed

+492
-110
lines changed

packages/service-library/src/servicelib/logging_utils.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,15 +415,17 @@ def log_context(
415415
if extra:
416416
kwargs["extra"] = extra
417417
log_msg = f"Starting {msg} ..."
418-
logger.log(level, log_msg, *args, **kwargs)
418+
419+
stackelvel = 3 # NOTE: 1 => log_context, 2 => contextlib, 3 => caller
420+
logger.log(level, log_msg, *args, **kwargs, stacklevel=stackelvel)
419421
yield
420422
duration = (
421423
f" in {(datetime.now() - start ).total_seconds()}s" # noqa: DTZ005
422424
if log_duration
423425
else ""
424426
)
425427
log_msg = f"Finished {msg}{duration}"
426-
logger.log(level, log_msg, *args, **kwargs)
428+
logger.log(level, log_msg, *args, **kwargs, stacklevel=stackelvel)
427429

428430

429431
def guess_message_log_level(message: str) -> LogLevelInt:

packages/service-library/tests/test_logging_utils.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
# pylint:disable=redefined-outer-name
2+
# pylint:disable=unused-argument
23

34
import logging
5+
from collections.abc import Iterable
46
from contextlib import suppress
7+
from pathlib import Path
58
from typing import Any
69

710
import pytest
@@ -243,6 +246,36 @@ def test_log_context(
243246
assert len(caplog.messages) == 2
244247

245248

249+
@pytest.fixture
250+
def log_format_with_module_name() -> Iterable[None]:
251+
for handler in logging.root.handlers:
252+
original_formatter = handler.formatter
253+
handler.setFormatter(
254+
logging.Formatter(
255+
"%(asctime)s %(levelname)s %(module)s:%(filename)s:%(lineno)d %(message)s",
256+
datefmt="%Y-%m-%d %H:%M:%S",
257+
)
258+
)
259+
260+
yield
261+
262+
for handler in logging.root.handlers:
263+
handler.formatter = original_formatter
264+
265+
266+
def test_log_context_caller_is_included_in_log(
267+
caplog: pytest.LogCaptureFixture,
268+
log_format_with_module_name: None,
269+
):
270+
caplog.clear()
271+
272+
with log_context(_logger, logging.ERROR, "a test message"):
273+
...
274+
275+
# Verify file name is in the log
276+
assert Path(__file__).name in caplog.text
277+
278+
246279
@pytest.mark.parametrize("level", _ALL_LOGGING_LEVELS, ids=_to_level_name)
247280
def test_logs_no_exceptions(caplog: pytest.LogCaptureFixture, level: int):
248281
caplog.set_level(level)

services/docker-compose.yml

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -552,36 +552,48 @@ services:
552552
- default
553553
- docker-api-network
554554
environment:
555-
LOG_FORMAT_LOCAL_DEV_ENABLED: ${LOG_FORMAT_LOCAL_DEV_ENABLED}
555+
CATALOG_HOST: ${CATALOG_HOST}
556+
CATALOG_PORT: ${CATALOG_PORT}
557+
DIRECTOR_V2_HOST: ${DIRECTOR_V2_HOST}
558+
DIRECTOR_V2_PORT: ${DIRECTOR_V2_PORT}
559+
560+
DOCKER_API_PROXY_HOST: ${DOCKER_API_PROXY_HOST}
561+
DOCKER_API_PROXY_PASSWORD: ${DOCKER_API_PROXY_PASSWORD}
562+
DOCKER_API_PROXY_PORT: ${DOCKER_API_PROXY_PORT}
563+
DOCKER_API_PROXY_SECURE: ${DOCKER_API_PROXY_SECURE}
564+
DOCKER_API_PROXY_USER: ${DOCKER_API_PROXY_USER}
565+
566+
DYNAMIC_SCHEDULER_LOGLEVEL: ${DYNAMIC_SCHEDULER_LOGLEVEL}
567+
DYNAMIC_SCHEDULER_PROFILING: ${DYNAMIC_SCHEDULER_PROFILING}
568+
DYNAMIC_SCHEDULER_STOP_SERVICE_TIMEOUT: ${DYNAMIC_SCHEDULER_STOP_SERVICE_TIMEOUT}
569+
DYNAMIC_SCHEDULER_TRACING: ${DYNAMIC_SCHEDULER_TRACING}
570+
DYNAMIC_SCHEDULER_UI_STORAGE_SECRET: ${DYNAMIC_SCHEDULER_UI_STORAGE_SECRET}
571+
DYNAMIC_SCHEDULER_USE_INTERNAL_SCHEDULER: ${DYNAMIC_SCHEDULER_USE_INTERNAL_SCHEDULER}
572+
DYNAMIC_SIDECAR_API_SAVE_RESTORE_STATE_TIMEOUT: ${DYNAMIC_SIDECAR_API_SAVE_RESTORE_STATE_TIMEOUT}
573+
556574
LOG_FILTER_MAPPING : ${LOG_FILTER_MAPPING}
575+
LOG_FORMAT_LOCAL_DEV_ENABLED: ${LOG_FORMAT_LOCAL_DEV_ENABLED}
576+
577+
POSTGRES_DB: ${POSTGRES_DB}
578+
POSTGRES_HOST: ${POSTGRES_HOST}
579+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
580+
POSTGRES_PORT: ${POSTGRES_PORT}
581+
POSTGRES_USER: ${POSTGRES_USER}
582+
557583
RABBIT_HOST: ${RABBIT_HOST}
558584
RABBIT_PASSWORD: ${RABBIT_PASSWORD}
559585
RABBIT_PORT: ${RABBIT_PORT}
560586
RABBIT_SECURE: ${RABBIT_SECURE}
561587
RABBIT_USER: ${RABBIT_USER}
588+
562589
REDIS_HOST: ${REDIS_HOST}
590+
REDIS_PASSWORD: ${REDIS_PASSWORD}
563591
REDIS_PORT: ${REDIS_PORT}
564592
REDIS_SECURE: ${REDIS_SECURE}
565593
REDIS_USER: ${REDIS_USER}
566-
REDIS_PASSWORD: ${REDIS_PASSWORD}
567-
CATALOG_HOST: ${CATALOG_HOST}
568-
CATALOG_PORT: ${CATALOG_PORT}
569-
DIRECTOR_V2_HOST: ${DIRECTOR_V2_HOST}
570-
DIRECTOR_V2_PORT: ${DIRECTOR_V2_PORT}
571-
DYNAMIC_SCHEDULER_USE_INTERNAL_SCHEDULER: ${DYNAMIC_SCHEDULER_USE_INTERNAL_SCHEDULER}
572-
DYNAMIC_SCHEDULER_LOGLEVEL: ${DYNAMIC_SCHEDULER_LOGLEVEL}
573-
DYNAMIC_SCHEDULER_STOP_SERVICE_TIMEOUT: ${DYNAMIC_SCHEDULER_STOP_SERVICE_TIMEOUT}
574-
DYNAMIC_SCHEDULER_PROFILING: ${DYNAMIC_SCHEDULER_PROFILING}
575-
DYNAMIC_SCHEDULER_TRACING: ${DYNAMIC_SCHEDULER_TRACING}
576-
DYNAMIC_SCHEDULER_UI_STORAGE_SECRET: ${DYNAMIC_SCHEDULER_UI_STORAGE_SECRET}
577-
DYNAMIC_SIDECAR_API_SAVE_RESTORE_STATE_TIMEOUT: ${DYNAMIC_SIDECAR_API_SAVE_RESTORE_STATE_TIMEOUT}
594+
578595
TRACING_OPENTELEMETRY_COLLECTOR_ENDPOINT: ${TRACING_OPENTELEMETRY_COLLECTOR_ENDPOINT}
579596
TRACING_OPENTELEMETRY_COLLECTOR_PORT: ${TRACING_OPENTELEMETRY_COLLECTOR_PORT}
580-
DOCKER_API_PROXY_HOST: ${DOCKER_API_PROXY_HOST}
581-
DOCKER_API_PROXY_PASSWORD: ${DOCKER_API_PROXY_PASSWORD}
582-
DOCKER_API_PROXY_PORT: ${DOCKER_API_PROXY_PORT}
583-
DOCKER_API_PROXY_SECURE: ${DOCKER_API_PROXY_SECURE}
584-
DOCKER_API_PROXY_USER: ${DOCKER_API_PROXY_USER}
585597
docker-api-proxy:
586598
image: ${DOCKER_REGISTRY:-itisfoundation}/docker-api-proxy:${DOCKER_IMAGE_TAG:-latest}
587599
init: true

services/dynamic-scheduler/requirements/_test.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,5 @@ pytest-runner
2626
pytest-sugar
2727
python-dotenv
2828
respx
29+
sqlalchemy[mypy]
30+
types-psycopg2

services/dynamic-scheduler/requirements/_test.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ greenlet==3.1.1
2727
# via
2828
# -c requirements/_base.txt
2929
# playwright
30+
# sqlalchemy
3031
h11==0.14.0
3132
# via
3233
# -c requirements/_base.txt
@@ -60,6 +61,10 @@ idna==3.10
6061
# requests
6162
iniconfig==2.0.0
6263
# via pytest
64+
mypy==1.15.0
65+
# via sqlalchemy
66+
mypy-extensions==1.1.0
67+
# via mypy
6368
packaging==24.2
6469
# via
6570
# -c requirements/_base.txt
@@ -112,13 +117,24 @@ sniffio==1.3.1
112117
# -c requirements/_base.txt
113118
# anyio
114119
# asgi-lifespan
120+
sqlalchemy==1.4.54
121+
# via
122+
# -c requirements/../../../requirements/constraints.txt
123+
# -c requirements/_base.txt
124+
# -r requirements/_test.in
125+
sqlalchemy2-stubs==0.0.2a38
126+
# via sqlalchemy
115127
termcolor==2.5.0
116128
# via pytest-sugar
129+
types-psycopg2==2.9.21.20250318
130+
# via -r requirements/_test.in
117131
typing-extensions==4.12.2
118132
# via
119133
# -c requirements/_base.txt
120134
# anyio
135+
# mypy
121136
# pyee
137+
# sqlalchemy2-stubs
122138
tzdata==2025.1
123139
# via faker
124140
urllib3==2.3.0

services/dynamic-scheduler/requirements/_tools.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,12 @@ isort==6.0.1
2828
mccabe==0.7.0
2929
# via pylint
3030
mypy==1.15.0
31-
# via -r requirements/../../../requirements/devenv.txt
32-
mypy-extensions==1.0.0
3331
# via
32+
# -c requirements/_test.txt
33+
# -r requirements/../../../requirements/devenv.txt
34+
mypy-extensions==1.1.0
35+
# via
36+
# -c requirements/_test.txt
3437
# black
3538
# mypy
3639
nodeenv==1.9.1

services/dynamic-scheduler/setup.cfg

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ commit_args = --no-verify
99

1010
[tool:pytest]
1111
asyncio_mode = auto
12-
markers =
12+
markers =
1313
testit: "marks test to run during development"
1414

1515
[mypy]
16-
plugins =
16+
plugins =
1717
pydantic.mypy
18+
sqlalchemy.ext.mypy.plugin

services/dynamic-scheduler/src/simcore_service_dynamic_scheduler/cli.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import typer
55
from settings_library.docker_api_proxy import DockerApiProxysettings
6+
from settings_library.postgres import PostgresSettings
67
from settings_library.rabbit import RabbitSettings
78
from settings_library.utils_cli import (
89
create_settings_command,
@@ -49,14 +50,29 @@ def echo_dotenv(ctx: typer.Context, *, minimal: bool = True):
4950
RABBIT_SECURE=os.environ.get("RABBIT_SECURE", "0"),
5051
RABBIT_USER=os.environ.get("RABBIT_USER", "replace-with-rabbit-user"),
5152
RABBIT_PASSWORD=os.environ.get(
52-
"RABBIT_PASSWORD", "replace-with-rabbit-user"
53+
"RABBIT_PASSWORD", "replace-with-rabbit-password"
5354
),
5455
),
5556
),
5657
DYNAMIC_SCHEDULER_UI_STORAGE_SECRET=os.environ.get(
5758
"DYNAMIC_SCHEDULER_UI_STORAGE_SECRET",
5859
"replace-with-ui-storage-secret",
5960
),
61+
DYNAMIC_SCHEDULER_POSTGRES=os.environ.get(
62+
"DYNAMIC_SCHEDULER_POSTGRES",
63+
PostgresSettings.create_from_envs(
64+
POSTGRES_HOST=os.environ.get(
65+
"POSTGRES_HOST", "replace-with-postgres-host"
66+
),
67+
POSTGRES_USER=os.environ.get(
68+
"POSTGRES_USER", "replace-with-postgres-user"
69+
),
70+
POSTGRES_PASSWORD=os.environ.get(
71+
"POSTGRES_PASSWORD", "replace-with-postgres-password"
72+
),
73+
POSTGRES_DB=os.environ.get("POSTGRES_DB", "replace-with-postgres-db"),
74+
),
75+
),
6076
DYNAMIC_SCHEDULER_DOCKER_API_PROXY=os.environ.get(
6177
"DYNAMIC_SCHEDULER_DOCKER_API_PROXY",
6278
DockerApiProxysettings.create_from_envs(

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,17 @@
66
create_remote_docker_client_input_state,
77
remote_docker_client_lifespan,
88
)
9+
from servicelib.fastapi.postgres_lifespan import (
10+
create_postgres_database_input_state,
11+
)
912
from servicelib.fastapi.prometheus_instrumentation import (
1013
create_prometheus_instrumentationmain_input_state,
1114
prometheus_instrumentation_lifespan,
1215
)
1316

1417
from .._meta import APP_FINISHED_BANNER_MSG, APP_STARTED_BANNER_MSG
1518
from ..api.rpc.routes import rpc_api_routes_lifespan
19+
from ..repository.events import repository_lifespan_manager
1620
from ..services.catalog import catalog_lifespan
1721
from ..services.deferred_manager import deferred_manager_lifespan
1822
from ..services.director_v0 import director_v0_lifespan
@@ -36,6 +40,7 @@ async def _settings_lifespan(app: FastAPI) -> AsyncIterator[State]:
3640
settings: ApplicationSettings = app.state.settings
3741

3842
yield {
43+
**create_postgres_database_input_state(settings.DYNAMIC_SCHEDULER_POSTGRES),
3944
**create_prometheus_instrumentationmain_input_state(
4045
enabled=settings.DYNAMIC_SCHEDULER_PROMETHEUS_INSTRUMENTATION_ENABLED
4146
),
@@ -49,6 +54,7 @@ def create_app_lifespan() -> LifespanManager:
4954
app_lifespan = LifespanManager()
5055
app_lifespan.add(_settings_lifespan)
5156

57+
app_lifespan.include(repository_lifespan_manager)
5258
app_lifespan.add(director_v2_lifespan)
5359
app_lifespan.add(director_v0_lifespan)
5460
app_lifespan.add(catalog_lifespan)

0 commit comments

Comments
 (0)