|
3 | 3 |
|
4 | 4 | """Module to define the client class.""" |
5 | 5 |
|
| 6 | +# pylint: disable=too-many-lines |
| 7 | + |
6 | 8 | from __future__ import annotations |
7 | 9 |
|
8 | 10 | import logging |
|
27 | 29 | from frequenz.client.common.pagination import Params |
28 | 30 | from google.protobuf import field_mask_pb2, struct_pb2 |
29 | 31 |
|
| 32 | +from ._backoff import Backoff |
30 | 33 | from ._types import ( |
31 | 34 | DeliveryArea, |
32 | 35 | DeliveryPeriod, |
@@ -91,7 +94,9 @@ def validate_decimal_places(value: Decimal, decimal_places: int, name: str) -> N |
91 | 94 | ) from exc |
92 | 95 |
|
93 | 96 |
|
94 | | -class Client(BaseApiClient[ElectricityTradingServiceStub]): |
| 97 | +class Client( |
| 98 | + BaseApiClient[ElectricityTradingServiceStub] |
| 99 | +): # pylint:disable=too-many-instance-attributes |
95 | 100 | """Electricity trading client.""" |
96 | 101 |
|
97 | 102 | _instances: dict[tuple[str, str | None], "Client"] = {} |
@@ -120,15 +125,28 @@ def __new__( |
120 | 125 |
|
121 | 126 | return cls._instances[key] |
122 | 127 |
|
123 | | - def __init__( |
124 | | - self, server_url: str, connect: bool = True, auth_key: str | None = None |
| 128 | + def __init__( # pylint: disable=too-many-arguments, too-many-positional-arguments |
| 129 | + self, |
| 130 | + server_url: str, |
| 131 | + connect: bool = True, |
| 132 | + auth_key: str | None = None, |
| 133 | + initial_timeout: float = 10.0, |
| 134 | + max_timeout: float = 300.0, |
| 135 | + timeout_growth_factor: float = 2.0, |
| 136 | + max_timeout_retries: int = 5, |
| 137 | + reset_interval: int = 600, |
125 | 138 | ) -> None: |
126 | 139 | """Initialize the client. |
127 | 140 |
|
128 | 141 | Args: |
129 | 142 | server_url: The URL of the Electricity Trading service. |
130 | 143 | connect: Whether to connect to the server immediately. |
131 | 144 | auth_key: The API key for the authorization. |
| 145 | + initial_timeout: Initial timeout duration for gRPC calls (in seconds). |
| 146 | + max_timeout: Maximum timeout duration for gRPC calls (in seconds). |
| 147 | + timeout_growth_factor: Factor by which to increase the timeout on each retry. |
| 148 | + max_timeout_retries: Maximum number of retry attempts when a timeout is reached. |
| 149 | + reset_interval: Time (in seconds) before resetting timeout if everything behaves fine. |
132 | 150 | """ |
133 | 151 | if not hasattr( |
134 | 152 | self, "_initialized" |
@@ -163,6 +181,15 @@ def __init__( |
163 | 181 |
|
164 | 182 | self._metadata = (("key", auth_key),) if auth_key else () |
165 | 183 |
|
| 184 | + # Backoff strategy configuration to handle gRPC connection failures |
| 185 | + self._backoff = Backoff( |
| 186 | + initial_timeout=initial_timeout, |
| 187 | + max_timeout=max_timeout, |
| 188 | + timeout_growth_factor=timeout_growth_factor, |
| 189 | + max_retries=max_timeout_retries, |
| 190 | + reset_interval=reset_interval, |
| 191 | + ) |
| 192 | + |
166 | 193 | @property |
167 | 194 | def stub(self) -> electricity_trading_pb2_grpc.ElectricityTradingServiceAsyncStub: |
168 | 195 | """ |
@@ -503,10 +530,10 @@ async def create_gridpool_order( |
503 | 530 | try: |
504 | 531 | response = await cast( |
505 | 532 | Awaitable[electricity_trading_pb2.CreateGridpoolOrderResponse], |
506 | | - self.stub.CreateGridpoolOrder( |
| 533 | + self._backoff.execute_with_backoff( |
| 534 | + self.stub.CreateGridpoolOrder, |
507 | 535 | electricity_trading_pb2.CreateGridpoolOrderRequest( |
508 | | - gridpool_id=gridpool_id, |
509 | | - order=order.to_pb(), |
| 536 | + gridpool_id=gridpool_id, order=order.to_pb() |
510 | 537 | ), |
511 | 538 | metadata=self._metadata, |
512 | 539 | ), |
@@ -615,7 +642,8 @@ async def update_gridpool_order( |
615 | 642 | try: |
616 | 643 | response = await cast( |
617 | 644 | Awaitable[electricity_trading_pb2.UpdateGridpoolOrderResponse], |
618 | | - self.stub.UpdateGridpoolOrder( |
| 645 | + self._backoff.execute_with_backoff( |
| 646 | + self.stub.UpdateGridpoolOrder, |
619 | 647 | electricity_trading_pb2.UpdateGridpoolOrderRequest( |
620 | 648 | gridpool_id=gridpool_id, |
621 | 649 | order_id=order_id, |
@@ -650,7 +678,8 @@ async def cancel_gridpool_order( |
650 | 678 | try: |
651 | 679 | response = await cast( |
652 | 680 | Awaitable[electricity_trading_pb2.CancelGridpoolOrderResponse], |
653 | | - self.stub.CancelGridpoolOrder( |
| 681 | + self._backoff.execute_with_backoff( |
| 682 | + self.stub.CancelGridpoolOrder, |
654 | 683 | electricity_trading_pb2.CancelGridpoolOrderRequest( |
655 | 684 | gridpool_id=gridpool_id, order_id=order_id |
656 | 685 | ), |
@@ -678,7 +707,8 @@ async def cancel_all_gridpool_orders(self, gridpool_id: int) -> int: |
678 | 707 | try: |
679 | 708 | response = await cast( |
680 | 709 | Awaitable[electricity_trading_pb2.CancelAllGridpoolOrdersResponse], |
681 | | - self.stub.CancelAllGridpoolOrders( |
| 710 | + self._backoff.execute_with_backoff( |
| 711 | + self.stub.CancelAllGridpoolOrders, |
682 | 712 | electricity_trading_pb2.CancelAllGridpoolOrdersRequest( |
683 | 713 | gridpool_id=gridpool_id |
684 | 714 | ), |
@@ -710,7 +740,8 @@ async def get_gridpool_order(self, gridpool_id: int, order_id: int) -> OrderDeta |
710 | 740 | try: |
711 | 741 | response = await cast( |
712 | 742 | Awaitable[electricity_trading_pb2.GetGridpoolOrderResponse], |
713 | | - self.stub.GetGridpoolOrder( |
| 743 | + self._backoff.execute_with_backoff( |
| 744 | + self.stub.GetGridpoolOrder, |
714 | 745 | electricity_trading_pb2.GetGridpoolOrderRequest( |
715 | 746 | gridpool_id=gridpool_id, order_id=order_id |
716 | 747 | ), |
@@ -770,7 +801,8 @@ async def list_gridpool_orders( |
770 | 801 | try: |
771 | 802 | response = await cast( |
772 | 803 | Awaitable[electricity_trading_pb2.ListGridpoolOrdersResponse], |
773 | | - self.stub.ListGridpoolOrders( |
| 804 | + self._backoff.execute_with_backoff( |
| 805 | + self.stub.ListGridpoolOrders, |
774 | 806 | electricity_trading_pb2.ListGridpoolOrdersRequest( |
775 | 807 | gridpool_id=gridpool_id, |
776 | 808 | filter=gridpool_order_filer.to_pb(), |
@@ -842,7 +874,8 @@ async def list_gridpool_trades( |
842 | 874 | try: |
843 | 875 | response = await cast( |
844 | 876 | Awaitable[electricity_trading_pb2.ListGridpoolTradesResponse], |
845 | | - self.stub.ListGridpoolTrades( |
| 877 | + self._backoff.execute_with_backoff( |
| 878 | + self.stub.ListGridpoolTrades, |
846 | 879 | electricity_trading_pb2.ListGridpoolTradesRequest( |
847 | 880 | gridpool_id=gridpool_id, |
848 | 881 | filter=gridpool_trade_filter.to_pb(), |
@@ -899,7 +932,8 @@ async def list_public_trades( |
899 | 932 | try: |
900 | 933 | response = await cast( |
901 | 934 | Awaitable[electricity_trading_pb2.ListPublicTradesResponse], |
902 | | - self.stub.ListPublicTrades( |
| 935 | + self._backoff.execute_with_backoff( |
| 936 | + self.stub.ListPublicTrades, |
903 | 937 | electricity_trading_pb2.ListPublicTradesRequest( |
904 | 938 | filter=public_trade_filter.to_pb(), |
905 | 939 | pagination_params=pagination_params.to_proto(), |
|
0 commit comments