Skip to content

Commit 40456d6

Browse files
authored
Initial structure (#9)
- Prepare dependencies for dispatch - Fix labeler path - Add initial structure
2 parents 8c9c1c7 + 35cb8de commit 40456d6

File tree

12 files changed

+639
-63
lines changed

12 files changed

+639
-63
lines changed

.github/labeler.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
# For more details on the configuration please see:
77
# https://github.com/marketplace/actions/labeler
88

9-
# TODO(cookiecutter): Add different parts of the source
109
# For example:
1110
#
1211
# "part:module":
@@ -65,4 +64,4 @@
6564
"part:actor":
6665
- changed-files:
6766
- any-glob-to-any-file:
68-
- "src/frequenz/dispatch/actor/**"
67+
- "src/frequenz/dispatch/actor.py"

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ jobs:
180180
--net=host \
181181
--platform linux/${{ matrix.arch }} \
182182
localhost/nox-cross-arch:latest \
183-
bash -c "pip install -e .[dev-noxfile]; nox --install-only -e ${{ matrix.nox-session }}; pip freeze; nox -e ${{ matrix.nox-session }}"
183+
bash -c "pip install -e .[dev-noxfile]; nox --install-only -e ${{ matrix.nox-session }}; pip freeze; nox -R -e ${{ matrix.nox-session }}"
184184
timeout-minutes: 30
185185

186186
# This ensures that the runner has access to the pip cache.

README.md

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,30 @@ It provides two channels for clients:
1515
## Example Usage
1616

1717
```python
18-
async def run():
19-
# dispatch helper sends out dispatches when they are due
20-
dispatch_arrived = dispatch_helper.new_dispatches().new_receiver()
21-
dispatch_ready = dispatch_helper.ready_dispatches().new_receiver()
22-
23-
async for selected in select(dispatch_ready, dispatch_arrived):
24-
if selected_from(selected, dispatch_arrived):
25-
dispatch = selected.value
26-
match dispatch.type:
27-
case DISPATCH_TYPE_BATTERY_CHARGE:
28-
battery_pool = microgrid.battery_pool(dispatch.battery_set, task_id)
29-
battery_pool.set_charge(dispatch.power)
30-
...
31-
if selected_from(selected, dispatch_ready):
32-
dispatch = selected.value
33-
log.info("New dispatch arrived %s", dispatch)
18+
async def run():
19+
# dispatch helper sends out dispatches when they are due
20+
dispatch_arrived = dispatch_helper.updated_dispatches().new_receiver()
21+
dispatch_ready = dispatch_helper.ready_dispatches().new_receiver()
22+
23+
async for selected in select(dispatch_ready, dispatch_arrived):
24+
if selected_from(selected, dispatch_ready):
25+
dispatch = selected.value
26+
match dispatch.type:
27+
case DISPATCH_TYPE_BATTERY_CHARGE:
28+
battery_pool = microgrid.battery_pool(dispatch.battery_set, task_id)
29+
battery_pool.set_charge(dispatch.power)
30+
...
31+
if selected_from(selected, dispatch_arrived):
32+
match selected.value:
33+
case Created(dispatch):
34+
log.info("New dispatch arrived %s", dispatch)
35+
...
36+
case Updated(dispatch):
37+
log.info("Dispatch updated %s", dispatch)
38+
...
39+
case Deleted(dispatch):
40+
log.info("Dispatch deleted %s", dispatch)
41+
...
3442
```
3543

3644
## Supported Platforms

mkdocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ plugins:
115115
# See https://mkdocstrings.github.io/python/usage/#import for details
116116
- https://docs.python.org/3/objects.inv
117117
- https://frequenz-floss.github.io/frequenz-channels-python/v0.16/objects.inv
118-
- https://frequenz-floss.github.io/frequenz-sdk-python/v0.25/objects.inv
118+
- https://frequenz-floss.github.io/frequenz-sdk-python/v1.0-pre/objects.inv
119119
- https://typing-extensions.readthedocs.io/en/stable/objects.inv
120120
- https://frequenz-floss.github.io/frequenz-client-dispatch-python/v0.1/objects.inv
121121
# Note this plugin must be loaded after mkdocstrings to be able to use macros

pyproject.toml

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ description = "A highlevel interface for the dispatch API"
1515
readme = "README.md"
1616
license = { text = "MIT" }
1717
keywords = ["frequenz", "python", "actor", "frequenz-dispatch", "dispatch", "highlevel", "api"]
18-
# TODO(cookiecutter): Remove and add more classifiers if appropriate
1918
classifiers = [
2019
"Development Status :: 3 - Alpha",
2120
"Intended Audience :: Developers",
@@ -26,21 +25,27 @@ classifiers = [
2625
"Typing :: Typed",
2726
]
2827
requires-python = ">= 3.11, < 4"
29-
# TODO(cookiecutter): Remove and add more dependencies if appropriate
3028
dependencies = [
29+
"python-dateutil >= 2.8.2, < 3.0",
3130
"typing-extensions == 4.10.0",
3231
# Make sure to update the version for cross-referencing also in the
3332
# mkdocs.yml file when changing the version here (look for the config key
3433
# plugins.mkdocstrings.handlers.python.import)
35-
"frequenz-sdk == 0.25.2",
34+
"frequenz-sdk == v1.0.0-rc5",
35+
"frequenz-channels == 1.0.0b2",
36+
"frequenz-dispatch-client @ git+https://github.com/frequenz-floss/frequenz-client-dispatch-python.git@00dcb3c",
37+
"frequenz-api-dispatch @ git+https://github.com/frequenz-floss/frequenz-api-dispatch.git@223315c",
38+
# "frequenz-api-dispatch >= 0.13.0, < 0.14",
39+
"frequenz-client-base >= 0.2.1, < 0.3.0",
40+
# Directly use unreleased commit until the first release
41+
"frequenz-client-common @ git+https://github.com/frequenz-floss/frequenz-client-common-python.git@5e6e7b7",
3642
]
3743
dynamic = ["version"]
3844

3945
[[project.authors]]
4046
name = "Frequenz Energy-as-a-Service GmbH"
4147
4248

43-
# TODO(cookiecutter): Remove and add more optional dependencies if appropriate
4449
[project.optional-dependencies]
4550
dev-flake8 = [
4651
"flake8 == 7.0.0",
@@ -64,11 +69,13 @@ dev-mkdocs = [
6469
dev-mypy = [
6570
"mypy == 1.8.0",
6671
"types-Markdown == 3.5.0.20240129",
72+
"types-python-dateutil==2.8.19.20240311",
6773
# For checking the noxfile, docs/ script, and tests
6874
"frequenz-dispatch[dev-mkdocs,dev-noxfile,dev-pytest]",
6975
]
7076
dev-noxfile = [
71-
"nox == 2023.4.22",
77+
"uv == 0.1.14",
78+
"nox == 2024.3.02",
7279
"frequenz-repo-config[lib] == 0.9.1",
7380
]
7481
dev-pylint = [
@@ -82,6 +89,7 @@ dev-pytest = [
8289
"pytest-mock == 3.12.0",
8390
"pytest-asyncio == 0.23.5",
8491
"async-solipsism == 0.5",
92+
"time-machine == 2.14.0",
8593
]
8694
dev = [
8795
"frequenz-dispatch[dev-mkdocs,dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]",
@@ -159,11 +167,15 @@ namespace_packages = true
159167
# used but getting the original ignored error when removing the type: ignore.
160168
# See for example: https://github.com/python/mypy/issues/2960
161169
#no_incremental = true
162-
packages = ["frequenz.actor.dispatch"]
170+
packages = ["frequenz.dispatch"]
163171
strict = true
164172

165173
[[tool.mypy.overrides]]
166-
module = ["mkdocs_macros.*"]
174+
module = [
175+
"mkdocs_macros.*",
176+
"async_solipsism",
177+
"async_solipsism.*",
178+
]
167179
ignore_missing_imports = true
168180

169181
[tool.setuptools_scm]

src/frequenz/actor/dispatch/__init__.py

Lines changed: 0 additions & 25 deletions
This file was deleted.

src/frequenz/dispatch/__init__.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# License: MIT
2+
# Copyright © 2024 Frequenz Energy-as-a-Service GmbH
3+
4+
"""A highlevel interface for the dispatch API."""
5+
6+
import grpc.aio
7+
from frequenz.channels import Broadcast, Receiver
8+
from frequenz.client.dispatch.types import Dispatch
9+
10+
from frequenz.dispatch.actor import DispatchActor, DispatchEvent
11+
12+
__all__ = ["Dispatcher"]
13+
14+
15+
class Dispatcher:
16+
"""A highlevel interface for the dispatch API.
17+
18+
This class provides a highlevel interface to the dispatch API.
19+
It provides two channels:
20+
21+
One that sends a dispatch event message whenever a dispatch is created, updated or deleted.
22+
23+
The other sends a dispatch message whenever a dispatch is ready to be
24+
executed according to the schedule.
25+
26+
allows to receive new dispatches and ready dispatches.
27+
28+
Example:
29+
```python
30+
from frequenz.dispatch import Dispatcher
31+
32+
async def run():
33+
dispatcher = Dispatcher(API_CONNECTION_INFO)
34+
dispatcher.start() # this will start the actor
35+
dispatch_arrived = dispatcher.new_dispatches().new_receiver()
36+
dispatch_ready = dispatcher.ready_dispatches().new_receiver()
37+
```
38+
"""
39+
40+
def __init__(
41+
self, microgrid_id: int, grpc_channel: grpc.aio.Channel, svc_addr: str
42+
):
43+
"""Initialize the dispatcher.
44+
45+
Args:
46+
microgrid_id: The microgrid id.
47+
grpc_channel: The gRPC channel.
48+
svc_addr: The service address.
49+
"""
50+
self._ready_channel = Broadcast[Dispatch]("ready_dispatches")
51+
self._updated_channel = Broadcast[DispatchEvent]("new_dispatches")
52+
self._actor = DispatchActor(
53+
microgrid_id,
54+
grpc_channel,
55+
svc_addr,
56+
self._updated_channel.new_sender(),
57+
self._ready_channel.new_sender(),
58+
)
59+
60+
async def start(self) -> None:
61+
"""Start the actor."""
62+
self._actor.start()
63+
64+
def updated_dispatches(self) -> Receiver[DispatchEvent]:
65+
"""Return new, updated or deleted dispatches receiver.
66+
67+
Returns:
68+
A new receiver for new dispatches.
69+
"""
70+
return self._updated_channel.new_receiver()
71+
72+
def ready_dispatches(self) -> Receiver[Dispatch]:
73+
"""Return ready dispatches receiver.
74+
75+
Returns:
76+
A new receiver for ready dispatches.
77+
"""
78+
return self._ready_channel.new_receiver()

0 commit comments

Comments
 (0)