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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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)