Skip to content

Commit 1576f82

Browse files
committed
using pydantic
passes unit tests now
1 parent ccd153a commit 1576f82

File tree

4 files changed

+78
-72
lines changed

4 files changed

+78
-72
lines changed

services/sidecar/src/simcore_service_sidecar/cli.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
from typing import List
23

34
import click
45

@@ -12,9 +13,8 @@
1213
@click.option("--user_id", default="0", help="The user ID")
1314
@click.option("--project_id", default="0", help="The project ID")
1415
@click.option("--node_id", default=None, help="The node ID or nothing")
15-
def main(job_id: str, user_id: str, project_id: str, node_id: str):
16+
def main(job_id: str, user_id: str, project_id: str, node_id: str) -> List[str]:
1617
from simcore_service_sidecar.core import SIDECAR
17-
import pdb; pdb.set_trace()
1818
log.info(
1919
"STARTING task processing for user %s, project %s, node %s",
2020
user_id,
@@ -31,3 +31,5 @@ def main(job_id: str, user_id: str, project_id: str, node_id: str):
3131
project_id,
3232
node_id,
3333
)
34+
35+
return next_task_nodes

services/sidecar/src/simcore_service_sidecar/core.py

+14-53
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@
66
from contextlib import contextmanager
77
from datetime import datetime
88
from pathlib import Path
9-
from typing import Dict, List, Union, Any
9+
from typing import Any, Dict
1010

11-
import aio_pika
12-
import aiofiles
13-
import attr
11+
# import aiofiles
1412
import docker
1513
from celery.utils.log import get_task_logger
14+
from pydantic import BaseModel
1615
from sqlalchemy import and_, exc
1716

1817
from servicelib.utils import logged_gather
@@ -26,7 +25,7 @@
2625
from . import config
2726
from .rabbitmq import RabbitMQ
2827
from .utils import (DbSettings, DockerSettings, ExecutorSettings, S3Settings,
29-
find_entry_point, is_node_ready, safe_channel)
28+
find_entry_point, is_node_ready)
3029

3130
log = get_task_logger(__name__)
3231
log.setLevel(config.SIDECAR_LOGLEVEL)
@@ -48,8 +47,7 @@ def session_scope(session_factory):
4847
finally:
4948
session.close()
5049

51-
@attr.s(auto_attribs=True)
52-
class Sidecar: # pylint: disable=too-many-instance-attributes
50+
class Sidecar(BaseModel):
5351
_rabbit_mq: RabbitMQ
5452
_docker: DockerSettings = DockerSettings()
5553
_s3: S3Settings = S3Settings()
@@ -153,34 +151,6 @@ async def _pull_image(self):
153151
log.exception(msg)
154152
raise docker.errors.APIError(msg)
155153

156-
async def _post_log(
157-
self, channel: pika.channel.Channel, msg: Union[str, List[str]]
158-
):
159-
log_data = {
160-
"Channel": "Log",
161-
"Node": self._task.node_id,
162-
"user_id": self._user_id,
163-
"project_id": self._task.project_id,
164-
"Messages": msg if isinstance(msg, list) else [msg],
165-
}
166-
log_body = json.dumps(log_data)
167-
channel.basic_publish(
168-
exchange=self._pika.log_channel, routing_key="", body=log_body
169-
)
170-
171-
async def _post_progress(self, channel, progress):
172-
prog_data = {
173-
"Channel": "Progress",
174-
"Node": self._task.node_id,
175-
"user_id": self._user_id,
176-
"project_id": self._task.project_id,
177-
"Progress": progress,
178-
}
179-
prog_body = json.dumps(prog_data)
180-
channel.basic_publish(
181-
exchange=self._pika.progress_channel, routing_key="", body=prog_body
182-
)
183-
184154
async def log_file_processor(self, log_file: Path) -> None:
185155
"""checks both container logs and the log_file if any
186156
"""
@@ -208,7 +178,6 @@ async def log_file_processor(self, log_file: Path) -> None:
208178

209179

210180
# try:
211-
# import pdb; pdb.set_trace()
212181
# TIME_BETWEEN_LOGS_S: int = 2
213182
# time_logs_sent = time.monotonic()
214183
# accumulated_logs = []
@@ -508,25 +477,17 @@ async def run(self):
508477
self._task.node_id,
509478
self._task.internal_id,
510479
)
511-
# NOTE: the rabbit has a timeout of 60seconds so blocking this channel for more is a no go.
512-
513-
with safe_channel(self._pika) as (channel, _):
514-
await self._post_log(channel, msg="Preprocessing start...")
515-
480+
await self._rabbit_mq.post_log_message("Preprocessing start...")
516481
await self.preprocess()
517-
518-
with safe_channel(self._pika) as (channel, _):
519-
await self._post_log(channel, msg="...preprocessing end")
520-
await self._post_log(channel, msg="Processing start...")
482+
await self._rabbit_mq.post_log_message("...preprocessing end")
483+
484+
await self._rabbit_mq.post_log_message("Processing start...")
521485
await self.process()
486+
await self._rabbit_mq.post_log_message("...processing end")
522487

523-
with safe_channel(self._pika) as (channel, _):
524-
await self._post_log(channel, msg="...processing end")
525-
await self._post_log(channel, msg="Postprocessing start...")
488+
await self._rabbit_mq.post_log_message("Postprocessing start...")
526489
await self.postprocess()
527-
528-
with safe_channel(self._pika) as (channel, _):
529-
await self._post_log(channel, msg="...postprocessing end")
490+
await self._rabbit_mq.post_log_message("...postprocessing end")
530491

531492
log.debug(
532493
"Running Pipeline DONE %s:node %s:internal id %s from container",
@@ -617,7 +578,7 @@ async def inspect(self, job_request_id: int, user_id: str, project_id: str, node
617578
return next_task_nodes
618579

619580
# the task is ready!
620-
task.job_id = celery_task.request.id
581+
task.job_id = job_request_id
621582
_session.add(task)
622583
_session.commit()
623584

@@ -632,7 +593,7 @@ async def inspect(self, job_request_id: int, user_id: str, project_id: str, node
632593
.one()
633594
)
634595

635-
if task.job_id != celery_task.request.id:
596+
if task.job_id != job_request_id:
636597
# somebody else was faster
637598
return next_task_nodes
638599
task.state = RUNNING
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,89 @@
1+
import json
12
import logging
3+
from typing import Dict, List, Union
24

35
import aio_pika
4-
import attr
56
import tenacity
7+
from pydantic import BaseModel
68

79
from servicelib.rabbitmq_utils import RabbitMQRetryPolicyUponInitialization
8-
from simcore_sdk.config.rabbit import Config, eval_broker
10+
from simcore_sdk.config.rabbit import Config as RabbitConfig
11+
from simcore_sdk.config.rabbit import eval_broker
912

1013
log = logging.getLogger(__file__)
1114

12-
@attr.s(auto_attribs=True)
13-
class RabbitMQ:
14-
_config: Config = Config()
15+
16+
class RabbitMQ(BaseModel):
17+
_config: RabbitConfig = RabbitConfig()
1518
_connection: aio_pika.RobustConnection = None
1619
_channel: aio_pika.Channel = None
17-
logs_exchange: aio_pika.Exchange = None
18-
progress_exchange: aio_pika.Exchange = None
20+
_logs_exchange: aio_pika.Exchange = None
21+
_progress_exchange: aio_pika.Exchange = None
22+
23+
class Config:
24+
25+
arbitrary_types_allowed = True
1926

2027
async def connect(self):
2128
url = eval_broker(self._config)
2229
await wait_till_rabbit_responsive(url)
2330

24-
2531
self._connection = await aio_pika.connect_robust(
26-
url,
27-
client_properties={"connection_name": "sidecar connection"},
32+
url, client_properties={"connection_name": "sidecar connection"},
2833
)
2934

3035
self._channel = await self._connection.channel()
31-
self.logs_exchange = await self._channel.declare_exchange(
36+
self._logs_exchange = await self._channel.declare_exchange(
3237
self._config.log_channel, aio_pika.ExchangeType.FANOUT, auto_delete=True
3338
)
34-
self.progress_exchange = await self._channel.declare_exchange(
35-
self._config.progress_channel, aio_pika.ExchangeType.FANOUT, auto_delete=True
39+
self._progress_exchange = await self._channel.declare_exchange(
40+
self._config.progress_channel,
41+
aio_pika.ExchangeType.FANOUT,
42+
auto_delete=True,
3643
)
3744

38-
async def post_message(self):
39-
45+
async def close(self):
46+
await self._channel.close()
47+
await self._connection.close()
48+
49+
async def _post_message(self, exchange: aio_pika.Exchange, data: Dict[str, str]):
50+
await exchange.publish(message=json.dumps(data))
51+
52+
async def post_log_message(
53+
self,
54+
user_id: str,
55+
project_id: str,
56+
node_id: str,
57+
log_msg: Union[str, List[str]],
58+
):
59+
await self._post_message(
60+
self._logs_exchange,
61+
data={
62+
"Channel": "Log",
63+
"Node": node_id,
64+
"user_id": user_id,
65+
"project_id": project_id,
66+
"Messages": log_msg if isinstance(log_msg, list) else [log_msg],
67+
},
68+
)
69+
70+
async def post_progress_message(
71+
self, user_id: str, project_id: str, node_id: str, progress_msg: str
72+
):
73+
await self._post_message(
74+
self._logs_exchange,
75+
data={
76+
"Channel": "Progress",
77+
"Node": node_id,
78+
"user_id": user_id,
79+
"project_id": project_id,
80+
"Messages": progress_msg,
81+
},
82+
)
4083

4184

4285
@tenacity.retry(**RabbitMQRetryPolicyUponInitialization().kwargs)
4386
async def wait_till_rabbit_responsive(url: str):
4487
connection = await aio_pika.connect(url)
4588
await connection.close()
46-
return True
89+
return True

services/sidecar/tests/conftest.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
@pytest.fixture(scope="session")
1717
def project_slug_dir():
18-
folder = current_dir.parent.parent
18+
folder = current_dir.parent
1919
assert folder.exists()
2020
assert any(folder.glob("src/simcore_service_sidecar"))
2121
return folder

0 commit comments

Comments
 (0)