diff --git a/src/pyDataInterface/data_service/abstract_data_service.py b/src/pyDataInterface/data_service/abstract_data_service.py index b87299c..be5bc0c 100644 --- a/src/pyDataInterface/data_service/abstract_data_service.py +++ b/src/pyDataInterface/data_service/abstract_data_service.py @@ -1,14 +1,81 @@ -from abc import ABC +from __future__ import annotations + +import asyncio +from abc import ABC, abstractmethod from collections.abc import Callable -from typing import Any +from typing import Any, TypedDict + +from pyDataInterface.data_service.data_service_list import DataServiceList class AbstractDataService(ABC): - __root__: "AbstractDataService" - _callback_manager: Any + __root__: AbstractDataService + _task_manager: AbstractTaskManager + _callback_manager: AbstractCallbackManager """ This is a CallbackManager. Cannot type this here as this would lead to a recursive loop. """ + _autostart_tasks: dict[str, tuple[Any]] + # _task_status_change_callbacks: list[Callable[[str, dict[str, Any] | None], None]] + # """A list of callback functions to be invoked when the status of a task (start or + # stop) changes.""" - _task_status_change_callbacks: list[Callable[[str, dict[str, Any] | None], None]] + +class TaskDict(TypedDict): + task: asyncio.Task[None] + kwargs: dict[str, Any] + + +class AbstractTaskManager(ABC): + _task_status_change_callbacks: list[Callable[[str, dict[str, Any] | None], Any]] + """A list of callback functions to be invoked when the status of a task (start or + stop) changes.""" + _tasks: dict[str, TaskDict] + """A dictionary to keep track of running tasks. The keys are the names of the + tasks and the values are TaskDict instances which include the task itself and + its kwargs. + """ + + @abstractmethod + def _set_start_and_stop_for_async_methods(self) -> None: + ... + + @abstractmethod + def start_autostart_tasks(self) -> None: + ... + + +class AbstractCallbackManager(ABC): + service: AbstractDataService + callbacks: set[Callable[[str, Any], None]] + _list_mapping: dict[int, DataServiceList] + """ + A dictionary mapping the id of the original lists to the corresponding + DataServiceList instances. + This is used to ensure that all references to the same list within the DataService + object point to the same DataServiceList, so that any modifications to that list can + be tracked consistently. The keys of the dictionary are the ids of the original + lists, and the values are the DataServiceList instances that wrap these lists. + """ + _notification_callbacks: list[Callable[[str, str, Any], Any]] = [] + """ + A list of callback functions that are executed when a change occurs in the + DataService instance. These functions are intended to handle or respond to these + changes in some way, such as emitting a socket.io message to the frontend. + + Each function in this list should be a callable that accepts three parameters: + + - parent_path (str): The path to the parent of the attribute that was changed. + - name (str): The name of the attribute that was changed. + - value (Any): The new value of the attribute. + + A callback function can be added to this list using the add_notification_callback + method. Whenever a change in the DataService instance occurs (or in its nested + DataService or DataServiceList instances), the emit_notification method is invoked, + which in turn calls all the callback functions in _notification_callbacks with the + appropriate arguments. + + This implementation follows the observer pattern, with the DataService instance as + the "subject" and the callback functions as the "observers". + """