329d9e2ad03675df091bf14469f8103a3865ad6b
[pti/o2.git] / o2app / bootstrap.py
1 # Copyright (C) 2021 Wind River Systems, Inc.
2 #
3 #  Licensed under the Apache License, Version 2.0 (the "License");
4 #  you may not use this file except in compliance with the License.
5 #  You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 #  Unless required by applicable law or agreed to in writing, software
10 #  distributed under the License is distributed on an "AS IS" BASIS,
11 #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 #  See the License for the specific language governing permissions and
13 #  limitations under the License.
14
15 from retry import retry
16 import inspect
17 from typing import Callable
18
19 from o2common.adapter.notifications import AbstractNotifications,\
20     SmoO2Notifications
21 from o2common.adapter import redis_eventpublisher
22 from o2common.service import unit_of_work
23 from o2common.service import messagebus
24
25 from o2app.service import handlers
26 from o2app.adapter.unit_of_work import SqlAlchemyUnitOfWork
27
28 from o2ims.adapter import orm as o2ims_orm
29 from o2dms.adapter import orm as o2dms_orm
30
31 from o2common.helper import o2logging
32 logger = o2logging.get_logger(__name__)
33
34
35 @retry(tries=100, delay=2, backoff=1)
36 def wait_for_db_ready(engine):
37     # wait for db up
38     logger.info("Wait for DB ready ...")
39     engine.connect()
40     logger.info("DB is ready")
41
42
43 def bootstrap(
44     start_orm: bool = True,
45     uow: unit_of_work.AbstractUnitOfWork = SqlAlchemyUnitOfWork(),
46     notifications: AbstractNotifications = None,
47     publish: Callable = redis_eventpublisher.publish,
48 ) -> messagebus.MessageBus:
49
50     if notifications is None:
51         notifications = SmoO2Notifications()
52
53     if start_orm:
54         with uow:
55             # get default engine if uow is by default
56             engine = uow.session.get_bind()
57
58             wait_for_db_ready(engine)
59             o2ims_orm.start_o2ims_mappers(engine)
60             o2dms_orm.start_o2dms_mappers(engine)
61
62     dependencies = {"uow": uow, "notifications": notifications,
63                     "publish": publish}
64     injected_event_handlers = {
65         event_type: [
66             inject_dependencies(handler, dependencies)
67             for handler in event_handlers
68         ]
69         for event_type, event_handlers in handlers.EVENT_HANDLERS.items()
70     }
71     injected_command_handlers = {
72         command_type: inject_dependencies(handler, dependencies)
73         for command_type, handler in handlers.COMMAND_HANDLERS.items()
74     }
75
76     bus = messagebus.MessageBus(
77         uow=uow,
78         event_handlers=injected_event_handlers,
79         command_handlers=injected_command_handlers,
80     )
81     messagebus.MessageBus.set_instance(bus)
82     return bus
83
84
85 def inject_dependencies(handler, dependencies):
86     params = inspect.signature(handler).parameters
87     deps = {
88         name: dependency
89         for name, dependency in dependencies.items()
90         if name in params
91     }
92     return lambda message: handler(message, **deps)