@@ -93,7 +93,7 @@ def generate_structures(element: str, factors: list) -> dict:
9393
9494from aiida .engine import submit
9595import datetime
96- from aiida_pythonjob import prepare_pyfunction_inputs
96+ from aiida_pythonjob import prepare_pyfunction_inputs , PyFunction
9797
9898
9999@pyfunction ()
@@ -111,39 +111,62 @@ async def add_async(x, y, time: float):
111111 function_inputs = {"x" : 2 , "y" : 3 , "time" : 2.0 },
112112)
113113
114- node = submit (add_async , ** inputs )
114+ node = submit (PyFunction , ** inputs )
115115
116- # %%
117- # Here is an example to monitor external events or conditions without blocking.
116+ # %%#
117+ # Killing an async process
118+ # ~~~~~~~~~~~~~~~~~~~~~~~~
119+ # Since async functions run as regular AiiDA processes, they can be controlled and killed
120+ # programmatically. This is useful for managing long-running or stuck tasks.
121+ # You can kill a running async function using the AiiDA command line interface.
122+ #
123+ # .. code-block:: bash
124+ #
125+ # $ verdi process kill <pk>
126+ #
127+ # Monitor external events
128+ # ------------------------
129+ #
130+ # Async functions are particularly useful for monitoring external events or conditions without blocking the AiiDA daemon.
118131# Here is an example that waits until a specified time.
119132#
120133
121134
122- @ pyfunction ()
123- async def monitor_time ( time : datetime . datetime ):
135+ async def monitor_time ( time : datetime . datetime , interval : float = 0.5 , timeout : float = 60.0 ):
136+ """Monitor the current time until it reaches the specified target time."""
124137 import asyncio
125138
126- # monitor until the specified time
139+ start_time = datetime . datetime . now ()
127140 while datetime .datetime .now () < time :
128141 print ("Waiting..." )
129- await asyncio .sleep (0.5 )
142+ await asyncio .sleep (interval )
143+ if (datetime .datetime .now () - start_time ).total_seconds () > timeout :
144+ raise TimeoutError ("Monitoring timed out." )
130145
131146
132147inputs = prepare_pyfunction_inputs (
133148 monitor_time ,
134- function_inputs = {"time" : datetime .datetime .now () + datetime .timedelta (seconds = 5 )},
149+ function_inputs = {"time" : datetime .datetime .now () + datetime .timedelta (seconds = 5 ), "interval" : 1.0 },
135150)
136151
137- node = submit (monitor_time , ** inputs )
152+ node = submit (PyFunction , ** inputs )
153+ # %%
154+ # For user's convenience, we provide a dedicated ``MonitorFunction`` class that inherits from ``PyFunction``.
155+ # User only need to write normal function, which returns True when the monitoring condition is met.
138156
139- # %%#
140- # Killing an async process
141- # ------------------------
142- # Since async functions run as regular AiiDA processes, they can be controlled and killed
143- # programmatically. This is useful for managing long-running or stuck tasks.
144- # You can kill a running async function using the AiiDA command line interface.
145- #
146- # .. code-block:: bash
147- #
148- # $ verdi process kill <pk>
149- #
157+ from aiida_pythonjob import MonitorPyFunction
158+
159+
160+ def monitor_time (time : datetime .datetime ):
161+ # return True when the current time is greater than the target time
162+ return datetime .datetime .now () > time
163+
164+
165+ inputs = prepare_pyfunction_inputs (
166+ monitor_time ,
167+ function_inputs = {"time" : datetime .datetime .now () + datetime .timedelta (seconds = 5 )},
168+ interval = 1.0 ,
169+ timeout = 20.0 ,
170+ )
171+
172+ node = submit (MonitorPyFunction , ** inputs )
0 commit comments