Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/fastcs/controllers/base_controller.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import asyncio
from collections import Counter
from collections.abc import Sequence
from copy import deepcopy
Expand Down Expand Up @@ -59,6 +60,7 @@ def __init__(
ios = ios or []
self._attribute_ref_io_map = {io.ref_type: io for io in ios}
self._validate_io(ios)
self._started_event: asyncio.Event = asyncio.Event()

def _find_type_hints(self):
"""Find `Attribute` and `Controller` type hints for introspection validation"""
Expand Down Expand Up @@ -166,6 +168,22 @@ def post_initialise(self):
"""Hook to call after all attributes added, before serving the application"""
self._validate_type_hints()
self._connect_attribute_ios()
self._started_event.set()

async def wait_for_startup(self, timeout: float | None = None) -> bool:
"""Wait for the controller to be fully started.

This method blocks until the controller has completed post_initialise,
making it ready for use.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not appear to be true - it times out and returns False. I think we probably want it to propagate the exception. If it times out what is the caller supposed to do other than stop the application?


:param timeout: Maximum time to wait in seconds. None means wait forever.
:return: True if startup completed, False if timeout occurred.
"""
try:
await asyncio.wait_for(self._started_event.wait(), timeout=timeout)
return True
except TimeoutError:
return False

def _validate_type_hints(self):
"""Validate all `Attribute` and `Controller` type-hints were introspected"""
Expand Down