81 lines
3.0 KiB
Python
81 lines
3.0 KiB
Python
import asyncio
|
|
from enum import Enum
|
|
from types import UnionType
|
|
from typing import List, Any, Dict
|
|
|
|
from django_scopes import scope
|
|
|
|
from cookbook.connectors.connector import Connector
|
|
from cookbook.connectors.homeassistant import HomeAssistant
|
|
from cookbook.models import ShoppingListEntry, Recipe, MealPlan, Space
|
|
|
|
|
|
class ActionType(Enum):
|
|
CREATED = 1
|
|
UPDATED = 2
|
|
DELETED = 3
|
|
|
|
|
|
class ConnectorManager:
|
|
_connectors: Dict[str, List[Connector]]
|
|
_listening_to_classes: UnionType = ShoppingListEntry | Recipe | MealPlan | Connector
|
|
|
|
def __init__(self):
|
|
self._connectors = dict()
|
|
|
|
def __call__(self, instance: Any, **kwargs) -> None:
|
|
if not isinstance(instance, self._listening_to_classes):
|
|
return
|
|
|
|
# If a Connector was changed/updated, refresh connector from the database for said space
|
|
purge_connector_cache = isinstance(instance, Connector)
|
|
|
|
space: Space = instance.space
|
|
if space.name in self._connectors and not purge_connector_cache:
|
|
connectors: List[Connector] = self._connectors[space.name]
|
|
else:
|
|
with scope(space=space):
|
|
connectors: List[Connector] = [HomeAssistant(config) for config in space.homeassistantconfig_set.all()]
|
|
self._connectors[space.name] = connectors
|
|
|
|
if len(connectors) == 0 or purge_connector_cache:
|
|
return
|
|
|
|
loop = asyncio.new_event_loop()
|
|
asyncio.set_event_loop(loop)
|
|
loop.run_until_complete(self.run_connectors(connectors, space, instance, **kwargs))
|
|
loop.close()
|
|
|
|
@staticmethod
|
|
async def run_connectors(connectors: List[Connector], space: Space, instance: Any, **kwargs):
|
|
action_type: ActionType
|
|
if "created" in kwargs and kwargs["created"]:
|
|
action_type = ActionType.CREATED
|
|
elif "created" in kwargs and not kwargs["created"]:
|
|
action_type = ActionType.UPDATED
|
|
elif "origin" in kwargs:
|
|
action_type = ActionType.DELETED
|
|
else:
|
|
return
|
|
|
|
tasks: List[asyncio.Task] = list()
|
|
|
|
if isinstance(instance, ShoppingListEntry):
|
|
shopping_list_entry: ShoppingListEntry = instance
|
|
|
|
match action_type:
|
|
case ActionType.CREATED:
|
|
for connector in connectors:
|
|
tasks.append(asyncio.create_task(connector.on_shopping_list_entry_created(space, shopping_list_entry)))
|
|
case ActionType.UPDATED:
|
|
for connector in connectors:
|
|
tasks.append(asyncio.create_task(connector.on_shopping_list_entry_updated(space, shopping_list_entry)))
|
|
case ActionType.DELETED:
|
|
for connector in connectors:
|
|
tasks.append(asyncio.create_task(connector.on_shopping_list_entry_deleted(space, shopping_list_entry)))
|
|
|
|
try:
|
|
await asyncio.gather(*tasks, return_exceptions=False)
|
|
except BaseException as e:
|
|
print("received an exception from one of the tasks: ", e)
|