11import asyncio
22from collections import defaultdict
3- from collections .abc import Callable
3+ from collections .abc import Callable , Coroutine
44
55from fastcs .cs_methods import Command , Put , Scan
66from fastcs .datatypes import T
77
8- from .attributes import AttrHandlerR , AttrHandlerW , AttrR , AttrW
8+ from .attributes import ONCE , AttrHandlerR , AttrHandlerW , AttrR , AttrW
99from .controller import BaseController , Controller
1010from .controller_api import ControllerAPI
1111from .exceptions import FastCSException
@@ -40,18 +40,19 @@ def __del__(self):
4040 self ._stop_scan_tasks ()
4141
4242 async def serve (self ):
43+ scans , initials = _get_scan_and_initial_coros (self .controller_api )
44+ self ._initial_coros += initials
4345 await self ._run_initial_coros ()
44- await self ._start_scan_tasks ()
46+ await self ._start_scan_tasks (scans )
4547
4648 async def _run_initial_coros (self ):
4749 for coro in self ._initial_coros :
4850 await coro ()
4951
50- async def _start_scan_tasks (self ):
51- self ._scan_tasks = {
52- self ._loop .create_task (coro ())
53- for coro in _get_scan_coros (self .controller_api )
54- }
52+ async def _start_scan_tasks (
53+ self , coros : list [Callable [[], Coroutine [None , None , None ]]]
54+ ):
55+ self ._scan_tasks = {self ._loop .create_task (coro ()) for coro in coros }
5556
5657 def _stop_scan_tasks (self ):
5758 for task in self ._scan_tasks :
@@ -96,15 +97,18 @@ async def callback(value):
9697 return callback
9798
9899
99- def _get_scan_coros (root_controller_api : ControllerAPI ) -> list [Callable ]:
100+ def _get_scan_and_initial_coros (
101+ root_controller_api : ControllerAPI ,
102+ ) -> tuple [list [Callable ], list [Callable ]]:
100103 scan_dict : dict [float , list [Callable ]] = defaultdict (list )
104+ initial_coros : list [Callable ] = []
101105
102106 for controller_api in root_controller_api .walk_api ():
103107 _add_scan_method_tasks (scan_dict , controller_api )
104- _add_attribute_updater_tasks (scan_dict , controller_api )
108+ _add_attribute_updater_tasks (scan_dict , initial_coros , controller_api )
105109
106110 scan_coros = _get_periodic_scan_coros (scan_dict )
107- return scan_coros
111+ return scan_coros , initial_coros
108112
109113
110114def _add_scan_method_tasks (
@@ -115,13 +119,17 @@ def _add_scan_method_tasks(
115119
116120
117121def _add_attribute_updater_tasks (
118- scan_dict : dict [float , list [Callable ]], controller_api : ControllerAPI
122+ scan_dict : dict [float , list [Callable ]],
123+ initial_coros : list [Callable ],
124+ controller_api : ControllerAPI ,
119125):
120126 for attribute in controller_api .attributes .values ():
121127 match attribute :
122128 case AttrR (updater = AttrHandlerR (update_period = update_period )) as attribute :
123129 callback = _create_updater_callback (attribute )
124- if update_period is not None :
130+ if update_period is ONCE :
131+ initial_coros .append (callback )
132+ elif update_period is not None :
125133 scan_dict [update_period ].append (callback )
126134
127135
0 commit comments