Mercurial > libervia-backend
annotate libervia/frontends/tools/aio.py @ 4127:5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
A first method lets run an async method from blocking code.
rel 424
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 03 Oct 2023 16:27:51 +0200 |
parents | |
children | 5de6f3595380 |
rev | line source |
---|---|
4127
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
1 #!/usr/bin/env python3 |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
2 |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
3 # Libervia AsyncIO helper methods |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
4 # Copyright (C) 2009-2023 Jérôme Poisson (goffi@goffi.org) |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
5 |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
6 # This program is free software: you can redistribute it and/or modify |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
7 # it under the terms of the GNU Affero General Public License as published by |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
8 # the Free Software Foundation, either version 3 of the License, or |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
9 # (at your option) any later version. |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
10 |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
11 # This program is distributed in the hope that it will be useful, |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
14 # GNU Affero General Public License for more details. |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
15 |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
16 # You should have received a copy of the GNU Affero General Public License |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
18 |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
19 import asyncio |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
20 from typing import Any, Coroutine |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
21 |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
22 from libervia.backend.core import log as logging |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
23 |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
24 log = logging.getLogger(__name__) |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
25 background_tasks = set() |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
26 |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
27 |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
28 def _on_task_done(task: asyncio.Future) -> None: |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
29 """Callback function to execute when a task is done. |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
30 |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
31 @param task: The completed task. |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
32 Note: The function removes the task from the tracking set and logs any exceptions |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
33 that might have occurred. |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
34 """ |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
35 background_tasks.discard(task) |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
36 e = task.exception() |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
37 if e is not None: |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
38 exc_info = (type(e), e, e.__traceback__) |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
39 log.error("Task failed:", exc_info=exc_info) |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
40 |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
41 |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
42 def run_async(async_method: Coroutine | asyncio.Future) -> None: |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
43 """Schedules and tracks an asynchronous method. |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
44 |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
45 @param async_method: The method to be scheduled for execution. |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
46 Note: The function keeps a strong reference to the task to prevent it from being |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
47 garbage-collected. In case of task failure, logs the error. |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
48 cf. https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
49 """ |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
50 if isinstance(async_method, asyncio.Future): |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
51 task = asyncio.ensure_future(async_method) |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
52 else: |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
53 task = asyncio.create_task(async_method) |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
54 |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
55 background_tasks.add(task) |
5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
56 task.add_done_callback(_on_task_done) |