Skip to content

Commit 256d3c4

Browse files
committed
Update docs and tests
1 parent 3934b7b commit 256d3c4

File tree

2 files changed

+44
-22
lines changed

2 files changed

+44
-22
lines changed

docs/gallery/autogen/pyfunction.py

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ def generate_structures(element: str, factors: list) -> dict:
9393

9494
from aiida.engine import submit
9595
import 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

132147
inputs = 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)

tests/test_monitor.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ def test_async_function_runs_and_returns_result():
1616
)
1717
result, node = run_get_node(MonitorPyFunction, **inputs)
1818
assert node.is_finished_ok
19-
assert "result" in result
2019
# The actual monitor function returns None
2120
assert result["result"].value is None
2221

0 commit comments

Comments
 (0)