Skip to content

Commit 7dcb2b0

Browse files
committed
Add section on spawning extra tasks
This section explains how to use the underlaying `BackgroundService` to spawn new tasks and get them automatically cancelled when stopping the actor. Signed-off-by: Leandro Lucarella <[email protected]>
1 parent d93561b commit 7dcb2b0

File tree

1 file changed

+49
-2
lines changed

1 file changed

+49
-2
lines changed

src/frequenz/sdk/actor/__init__.py

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,57 @@ class and implement the abstract `_run()` method.
195195
any other more graceful way to stop the actor if you need to make sure it can't be
196196
interrupted at any `await` point.
197197
198+
### Spawning Extra Tasks
199+
200+
Actors run at least one background task, created automatically by the `Actor` class. But
201+
`Actor` inherits from [`BackgroundService`][frequenz.sdk.actor.BackgroundService], which
202+
provides a few methods to create and manage extra tasks.
203+
204+
If your actor needs to spawn extra tasks, you can use
205+
[`BackgroundService`][frequenz.sdk.actor.BackgroundService] facilities to manage the
206+
tasks, so they are also automatically stopped when the actor is stopped.
207+
208+
All you need to do is add the newly spawned tasks to the actor's
209+
[`tasks`][frequenz.sdk.actor.Actor.tasks] set.
210+
211+
???+ example
212+
213+
```python
214+
import asyncio
215+
from frequenz.sdk.actor import Actor
216+
217+
class MyActor(Actor):
218+
async def _run(self) -> None:
219+
extra_task = asyncio.create_task(self._extra_task()) # (1)!
220+
self.tasks.add(extra_task) # (2)!
221+
while True: # (3)!
222+
print("_run() running")
223+
await asyncio.sleep(1)
224+
225+
async def _extra_task(self) -> None:
226+
while True: # (4)!
227+
print("_extra_task() running")
228+
await asyncio.sleep(1.1) # (4)!
229+
230+
async with MyActor() as actor: # (5)!
231+
await asyncio.sleep(3) # (6)!
232+
# (7)!
233+
```
234+
235+
1. We create a new task using [`asyncio.create_task()`][asyncio.create_task].
236+
2. We add the task to the actor's [`tasks`][frequenz.sdk.actor.Actor.tasks] set.
237+
This ensures the task will be cancelled and cleaned up when the actor is stopped.
238+
3. We leave the actor running forever.
239+
4. The extra task will also run forever.
240+
5. The actor is started.
241+
6. We wait for 3 seconds, the actor should print a bunch of "_run() running" and
242+
"_extra_task() running" messages while it's running.
243+
7. The actor is stopped and the extra task is cancelled automatically.
244+
198245
### Examples
199246
200-
Here are a few simple but complete examples to demonstrate how to create create actors
201-
and connect them using [channels][frequenz.channels].
247+
Here are a few simple but complete examples to demonstrate how to create actors and
248+
connect them using [channels][frequenz.channels].
202249
203250
!!! tip
204251

0 commit comments

Comments
 (0)