Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Dispatch Highlevel Interface Release Notes

## Upgrading

- The minimum `frequenz-channels` version will be 1.13.0. Until it is released, the dependency temporarily points at [PR 595](https://github.com/frequenz-floss/frequenz-channels-python/pull/595).
- The minimum `frequenz-core` version is now 1.6.0, and the minimum `typing-extensions` version is now 4.16.0. These versions are required by `frequenz-channels` 1.13.0 too.
- The internal timers now use `MonotonicTimer`, and channel shutdown uses `aclose`. These replace APIs that `frequenz-channels` v2 removes. The public dispatch API and behavior are unchanged.

## Enhancements

- Improved docstring documentation across the project.
Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ classifiers = [
]
requires-python = ">= 3.11, < 4"
dependencies = [
"typing-extensions >= 4.13.0, < 5.0.0",
"typing-extensions >= 4.16.0, < 5.0.0",
# Make sure to update the version for cross-referencing also in the
# mkdocs.yml file when changing the version here (look for the config key
# plugins.mkdocstrings.handlers.python.inventories)
"frequenz-sdk >= 1.0.0-rc2100, < 1.0.0-rc2300",
"frequenz-channels >= 1.6.1, < 2.0.0",
"frequenz-channels @ git+https://github.com/frequenz-floss/frequenz-channels-python@refs/pull/595/head",
"frequenz-client-dispatch >= 0.11.3, < 2.0.0",
"frequenz-client-base >= 0.11.0, < 0.12.0",
"frequenz-client-common >= 0.3.8, < 0.4.0",
"frequenz-core >= 1.0.2, < 2.0.0",
"frequenz-core >= 1.6.0, < 2.0.0",
"grpcio >= 1.80.0, < 2.0.0",
]
dynamic = ["version"]
Expand Down
6 changes: 3 additions & 3 deletions src/frequenz/dispatch/_actor_dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from warnings import warn

from frequenz.channels import Broadcast, Receiver, Sender, select
from frequenz.channels.timer import SkipMissedAndDrift, Timer
from frequenz.channels.timer import MonotonicTimer, SkipMissedAndDrift
from frequenz.client.dispatch.types import DispatchId, TargetComponents
from frequenz.core.id import BaseId
from frequenz.sdk.actor import Actor, BackgroundService
Expand Down Expand Up @@ -241,7 +241,7 @@ def __init__( # pylint: disable=too-many-arguments, too-many-positional-argumen
)

self._dispatch_rx = running_status_receiver
self._retry_timer_rx = Timer(retry_interval, SkipMissedAndDrift())
self._retry_timer_rx = MonotonicTimer(retry_interval, SkipMissedAndDrift())
self._actor_factory = actor_factory
self._actors: dict[DispatchActorId, ActorDispatcher.ActorAndChannel] = {}
self._failed_dispatches: dict[DispatchActorId, Dispatch] = {}
Expand Down Expand Up @@ -313,7 +313,7 @@ async def _stop_actor(self, stopping_dispatch: Dispatch, msg: str) -> None:
if actor_and_channel := self._actors.pop(identity, None):
_logger.info("Stopping actor for dispatch type %r", stopping_dispatch.type)
await actor_and_channel.actor.stop(msg)
await actor_and_channel.channel.close()
await actor_and_channel.channel.aclose()
else:
_logger.warning(
"Actor for dispatch type %r is not running, ignoring stop request",
Expand Down
19 changes: 13 additions & 6 deletions src/frequenz/dispatch/_bg_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import grpc.aio
from frequenz.channels import Broadcast, Receiver, select, selected_from
from frequenz.channels.timer import SkipMissedAndResync, Timer
from frequenz.channels.timer import MonotonicTimer, SkipMissedAndResync
from frequenz.client.base.streaming import (
StreamFatalError,
StreamRetrying,
Expand Down Expand Up @@ -257,7 +257,9 @@ async def _run(self) -> None: # pylint: disable=too-many-branches

# Streaming updates
with closing(
Timer(timedelta(seconds=100), SkipMissedAndResync(), auto_start=False)
MonotonicTimer(
timedelta(seconds=100), SkipMissedAndResync(), auto_start=False
)
) as next_event_timer:
# Initial fetch
await self._fetch(next_event_timer)
Expand Down Expand Up @@ -366,7 +368,9 @@ async def _run(self) -> None: # pylint: disable=too-many-branches
case StreamFatalError():
pass

async def _execute_scheduled_event(self, dispatch: Dispatch, timer: Timer) -> None:
async def _execute_scheduled_event(
self, dispatch: Dispatch, timer: MonotonicTimer
) -> None:
"""Execute a scheduled event and schedule the next one if any.

Args:
Expand All @@ -388,7 +392,7 @@ async def _execute_scheduled_event(self, dispatch: Dispatch, timer: Timer) -> No

self._update_timer(timer)

async def _fetch(self, timer: Timer) -> None:
async def _fetch(self, timer: MonotonicTimer) -> None:
"""Fetch all relevant dispatches using list.

This is used for the initial fetch and for re-fetching all dispatches
Expand Down Expand Up @@ -472,7 +476,10 @@ async def _fetch(self, timer: Timer) -> None:
self._initial_fetch_event.set()

async def _update_dispatch_schedule_and_notify(
self, dispatch: Dispatch | None, old_dispatch: Dispatch | None, timer: Timer
self,
dispatch: Dispatch | None,
old_dispatch: Dispatch | None,
timer: MonotonicTimer,
) -> None:
"""Update the schedule for a dispatch.

Expand Down Expand Up @@ -541,7 +548,7 @@ async def _update_dispatch_schedule_and_notify(
# We modified the schedule, so we need to reset the timer
self._update_timer(timer)

def _update_timer(self, timer: Timer) -> None:
def _update_timer(self, timer: MonotonicTimer) -> None:
"""Update the timer to the next event."""
if self._scheduled_events:
due_at: datetime = self._scheduled_events[0].time
Expand Down