Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revamp BackgroundService and rename to Service #27

Merged
merged 10 commits into from
Jul 30, 2024

Conversation

llucax
Copy link
Contributor

@llucax llucax commented Jul 26, 2024

The name BackgroundService is a bit too verbose now in the context of an asyncio library. Services are usually already understood as running in the background, so the Background prefix is redundant and makes the class name too long.

The Service class is made an abstract base class intended for end users that just want to use services, and a new ServiceBase class is added for developers that want to implement services. This way, the documentation can be separated between the two use cases and the Service class can be used as a generic type for services. We also avoid leaking implementation details to services users.

The ServiceBase class also have a new method create_task that is used to create tasks in the service, and a new TaskCreator protocol is added to allow overriding how tasks are created (for example, using a custom loop or a TaskGroup). create_task automatically adds the task to the internal set, so hopefully users won't forget so easily to register tasks.

The create_task method also have a new log_exceptions parameter that allows to log exceptions raised by tasks. This is useful because services tasks are supposed to run forever, and there are no many opportunities to await for their completion appropriately and handle the failure. With this at least we make sure we will get a log message when a task raises an exception, so we can at least know what happened and they just silently disappear.

Fixes #8, improves #9.

@llucax llucax requested a review from a team as a code owner July 26, 2024 16:13
@github-actions github-actions bot added part:tests Affects the unit, integration and performance (benchmarks) tests part:asyncio Affects the asyncio module labels Jul 26, 2024
@llucax llucax self-assigned this Jul 26, 2024
@llucax llucax added this to the v1.0.0 milestone Jul 26, 2024
@llucax llucax added type:enhancement New feature or enhancement visitble to users cmd:skip-release-notes It is not necessary to update release notes for this PR labels Jul 26, 2024
llucax added 10 commits July 26, 2024 18:19
This is not necessary, as properties should be documented as attributes.

Signed-off-by: Leandro Lucarella <[email protected]>
The name `BackgroundService` is a bit too verbose now in the context of
an asyncio library. Services are usually already understood as running
in the background, so the `Background` prefix is redundant and makes the
class name too long.

Signed-off-by: Leandro Lucarella <[email protected]>
This will be used in the future to allow overriding where to create
tasks (for example the default `asyncio` loop, a custom `loop` or even
a `TaskGroup`).

Signed-off-by: Leandro Lucarella <[email protected]>
This change adds a new parameter to the Service class, `task_creator`,
that will be used to create tasks. This is useful to allow the user to
use different task creators, like the `asyncio` module or a `TaskGroup`.

A method to create tasks was also added to the Service class, that uses
the task creator object to create the tasks, hopefully making it easier
for users not to forget to register tasks managed by the service in the
`self._tasks` set.

Signed-off-by: Leandro Lucarella <[email protected]>
It is common that users forget to handle exceptions properly in their
tasks, and since services tasks are supposed to run forever, there are
no many opportunities to await for their completion appropriately and
handle the failure.

With this at least we make sure we will get a log message when a task
raises an exception, so we can at least know what happened and they just
silently disappear.

Signed-off-by: Leandro Lucarella <[email protected]>
This makes it much easier when debugging to know which service spawned
each task.

Signed-off-by: Leandro Lucarella <[email protected]>
The warning is not very clear and might suggest users need to hold
references to the service's tasks, which is not correct, only a
reference to the service itself should be saved.

Signed-off-by: Leandro Lucarella <[email protected]>
By having both mixed up, it was hard to separate documentation for users
of services, and developers wanting to implement services. It also gave
access to service users to internals for service implementation, like
`create_task`, which is not ideal.

Now users can use the `Service` type to refer to services generically
and implementors can use `ServiceBase` to have a sane starting point to
implement a service.

Signed-off-by: Leandro Lucarella <[email protected]>
We don't really need to make it a public method, as one can just use
`await service` to await for it. It is still good to have it separate
as implementing `__await__` is easier based on another awaitable.

Signed-off-by: Leandro Lucarella <[email protected]>
@llucax llucax added this pull request to the merge queue Jul 30, 2024
Merged via the queue into frequenz-floss:v1.x.x with commit 79776f0 Jul 30, 2024
14 checks passed
@llucax llucax deleted the service branch July 30, 2024 14:34
github-merge-queue bot pushed a commit that referenced this pull request Aug 9, 2024
`asyncio.TaskGroup` is a very convenient construct when using
parallelization for doing calculations for example, where the results
for all the tasks need to be merged together to produce a final result.
In this case if one of the tasks fails, it makes sense to cancel the
others and abort as soon as possible, as any further calculations would
be thrown away.

This PR introduces a new `PersistentTaskGroup` class, intended to help
managing a group of tasks that should persist even if other tasks in the
group fail, usually by either only discarding the failed task or by
restarting it somehow.

The `ServiceBase` class is updated to use a `PersistentTaskGroup`
underneath, and it is simplified for single-task services by making the
service driven by a single `main` task, which can use the new group to
monitor sub-tasks and act accordingly.

This is part of #27 and #9.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cmd:skip-release-notes It is not necessary to update release notes for this PR part:asyncio Affects the asyncio module part:tests Affects the unit, integration and performance (benchmarks) tests type:enhancement New feature or enhancement visitble to users
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve the BackgroundService interface to handling internal tasks
2 participants