Skip to content

Commit

Permalink
Set appropriate timeouts for clients without option (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
mdegat01 authored Oct 26, 2024
1 parent dd6486f commit 0089da8
Show file tree
Hide file tree
Showing 12 changed files with 51 additions and 26 deletions.
9 changes: 5 additions & 4 deletions aiohasupervisor/addons.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Any

from .client import _SupervisorComponentClient
from .const import ResponseType
from .const import TIMEOUT_60_SECONDS, ResponseType
from .models.addons import (
AddonsConfigValidate,
AddonsList,
Expand Down Expand Up @@ -38,19 +38,20 @@ async def uninstall_addon(
await self._client.post(
f"addons/{addon}/uninstall",
json=options.to_dict() if options else None,
timeout=TIMEOUT_60_SECONDS,
)

async def start_addon(self, addon: str) -> None:
"""Start an addon."""
await self._client.post(f"addons/{addon}/start")
await self._client.post(f"addons/{addon}/start", timeout=TIMEOUT_60_SECONDS)

async def stop_addon(self, addon: str) -> None:
"""Stop an addon."""
await self._client.post(f"addons/{addon}/stop")
await self._client.post(f"addons/{addon}/stop", timeout=TIMEOUT_60_SECONDS)

async def restart_addon(self, addon: str) -> None:
"""Restart an addon."""
await self._client.post(f"addons/{addon}/restart")
await self._client.post(f"addons/{addon}/restart", timeout=None)

async def addon_options(self, addon: str, options: AddonsOptions) -> None:
"""Set options for addon."""
Expand Down
4 changes: 4 additions & 0 deletions aiohasupervisor/backups.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ async def full_backup(self, options: FullBackupOptions | None = None) -> NewBack
"backups/new/full",
json=options.to_dict() if options else None,
response_type=ResponseType.JSON,
timeout=None,
)
return NewBackup.from_dict(result.data)

Expand All @@ -64,6 +65,7 @@ async def partial_backup(self, options: PartialBackupOptions) -> NewBackup:
"backups/new/partial",
json=options.to_dict(),
response_type=ResponseType.JSON,
timeout=None,
)
return NewBackup.from_dict(result.data)

Expand All @@ -84,6 +86,7 @@ async def full_restore(
f"backups/{backup}/restore/full",
json=options.to_dict() if options else None,
response_type=ResponseType.JSON,
timeout=None,
)
return BackupJob.from_dict(result.data)

Expand All @@ -95,6 +98,7 @@ async def partial_restore(
f"backups/{backup}/restore/partial",
json=options.to_dict(),
response_type=ResponseType.JSON,
timeout=None,
)
return BackupJob.from_dict(result.data)

Expand Down
19 changes: 11 additions & 8 deletions aiohasupervisor/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
)
from yarl import URL

from .const import ResponseType
from .const import DEFAULT_TIMEOUT, ResponseType
from .exceptions import (
SupervisorAuthenticationError,
SupervisorBadRequestError,
Expand Down Expand Up @@ -50,15 +50,9 @@ class _SupervisorClient:

api_host: str
token: str
request_timeout: int
session: ClientSession | None = None
_close_session: bool = field(default=False, init=False)

@property
def timeout(self) -> ClientTimeout:
"""Timeout for requests."""
return ClientTimeout(total=self.request_timeout)

async def _request(
self,
method: HTTPMethod,
Expand All @@ -68,6 +62,7 @@ async def _request(
response_type: ResponseType,
json: dict[str, Any] | None = None,
data: Any = None,
timeout: ClientTimeout | None = DEFAULT_TIMEOUT,
) -> Response:
"""Handle a request to Supervisor."""
try:
Expand Down Expand Up @@ -102,7 +97,7 @@ async def _request(
async with self.session.request(
method.value,
url,
timeout=self.timeout,
timeout=timeout,
headers=headers,
params=params,
json=json,
Expand Down Expand Up @@ -153,13 +148,15 @@ async def get(
*,
params: dict[str, str] | None = None,
response_type: ResponseType = ResponseType.JSON,
timeout: ClientTimeout | None = DEFAULT_TIMEOUT,
) -> Response:
"""Handle a GET request to Supervisor."""
return await self._request(
HTTPMethod.GET,
uri,
params=params,
response_type=response_type,
timeout=timeout,
)

async def post(
Expand All @@ -170,6 +167,7 @@ async def post(
response_type: ResponseType = ResponseType.NONE,
json: dict[str, Any] | None = None,
data: Any = None,
timeout: ClientTimeout | None = DEFAULT_TIMEOUT,
) -> Response:
"""Handle a POST request to Supervisor."""
return await self._request(
Expand All @@ -179,6 +177,7 @@ async def post(
response_type=response_type,
json=json,
data=data,
timeout=timeout,
)

async def put(
Expand All @@ -187,6 +186,7 @@ async def put(
*,
params: dict[str, str] | None = None,
json: dict[str, Any] | None = None,
timeout: ClientTimeout | None = DEFAULT_TIMEOUT,
) -> Response:
"""Handle a PUT request to Supervisor."""
return await self._request(
Expand All @@ -195,20 +195,23 @@ async def put(
params=params,
response_type=ResponseType.NONE,
json=json,
timeout=timeout,
)

async def delete(
self,
uri: str,
*,
params: dict[str, str] | None = None,
timeout: ClientTimeout | None = DEFAULT_TIMEOUT,
) -> Response:
"""Handle a DELETE request to Supervisor."""
return await self._request(
HTTPMethod.DELETE,
uri,
params=params,
response_type=ResponseType.NONE,
timeout=timeout,
)

async def close(self) -> None:
Expand Down
5 changes: 5 additions & 0 deletions aiohasupervisor/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

from enum import StrEnum

from aiohttp import ClientTimeout

DEFAULT_TIMEOUT = ClientTimeout(total=10)
TIMEOUT_60_SECONDS = ClientTimeout(total=60)


class ResponseType(StrEnum):
"""Expected response type."""
Expand Down
4 changes: 2 additions & 2 deletions aiohasupervisor/discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from uuid import UUID

from .client import _SupervisorComponentClient
from .const import ResponseType
from .const import TIMEOUT_60_SECONDS, ResponseType
from .models.discovery import Discovery, DiscoveryConfig, DiscoveryList, SetDiscovery


Expand All @@ -12,7 +12,7 @@ class DiscoveryClient(_SupervisorComponentClient):

async def list(self) -> list[Discovery]:
"""List discovered active services."""
result = await self._client.get("discovery")
result = await self._client.get("discovery", timeout=TIMEOUT_60_SECONDS)
return DiscoveryList.from_dict(result.data).discovery

async def get(self, uuid: UUID) -> Discovery:
Expand Down
2 changes: 1 addition & 1 deletion aiohasupervisor/homeassistant.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ async def options(self, options: HomeAssistantOptions) -> None:
async def update(self, options: HomeAssistantUpdateOptions | None = None) -> None:
"""Update Home Assistant."""
await self._client.post(
"core/update", json=options.to_dict() if options else None
"core/update", json=options.to_dict() if options else None, timeout=None
)

async def restart(self, options: HomeAssistantRestartOptions | None = None) -> None:
Expand Down
5 changes: 4 additions & 1 deletion aiohasupervisor/host.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Host client for supervisor."""

from .client import _SupervisorComponentClient
from .const import TIMEOUT_60_SECONDS
from .models.host import (
HostInfo,
HostOptions,
Expand All @@ -22,7 +23,9 @@ async def info(self) -> HostInfo:
async def reboot(self, options: RebootOptions | None = None) -> None:
"""Reboot host."""
await self._client.post(
"host/reboot", json=options.to_dict() if options else None
"host/reboot",
json=options.to_dict() if options else None,
timeout=TIMEOUT_60_SECONDS,
)

async def shutdown(self, options: ShutdownOptions | None = None) -> None:
Expand Down
2 changes: 1 addition & 1 deletion aiohasupervisor/os.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ async def info(self) -> OSInfo:
async def update(self, options: OSUpdate | None = None) -> None:
"""Update OS."""
await self._client.post(
"os/update", json=options.to_dict() if options else None
"os/update", json=options.to_dict() if options else None, timeout=None
)

async def config_sync(self) -> None:
Expand Down
2 changes: 1 addition & 1 deletion aiohasupervisor/resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ async def run_check(self, check: CheckType | str) -> None:

async def apply_suggestion(self, suggestion: UUID) -> None:
"""Apply a suggestion."""
await self._client.post(f"resolution/suggestion/{suggestion.hex}")
await self._client.post(f"resolution/suggestion/{suggestion.hex}", timeout=None)

async def dismiss_suggestion(self, suggestion: UUID) -> None:
"""Dismiss a suggestion."""
Expand Down
7 changes: 3 additions & 4 deletions aiohasupervisor/root.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from typing import Self

from aiohttp import ClientSession
from aiohttp import ClientSession, ClientTimeout

from .addons import AddonsClient
from .backups import BackupsClient
Expand All @@ -25,11 +25,10 @@ def __init__(
self,
api_host: str,
token: str,
request_timeout: int = 10,
session: ClientSession | None = None,
) -> None:
"""Initialize client."""
self._client = _SupervisorClient(api_host, token, request_timeout, session)
self._client = _SupervisorClient(api_host, token, session)
self._addons = AddonsClient(self._client)
self._os = OSClient(self._client)
self._backups = BackupsClient(self._client)
Expand Down Expand Up @@ -98,7 +97,7 @@ async def info(self) -> RootInfo:

async def refresh_updates(self) -> None:
"""Refresh updates."""
await self._client.post("refresh_updates")
await self._client.post("refresh_updates", timeout=ClientTimeout(total=300))

async def available_updates(self) -> list[AvailableUpdate]:
"""Get available updates."""
Expand Down
6 changes: 4 additions & 2 deletions aiohasupervisor/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,16 @@ async def addon_documentation(self, addon: str) -> str:

async def install_addon(self, addon: str) -> None:
"""Install an addon."""
await self._client.post(f"store/addons/{addon}/install")
await self._client.post(f"store/addons/{addon}/install", timeout=None)

async def update_addon(
self, addon: str, options: StoreAddonUpdate | None = None
) -> None:
"""Update an addon to latest version."""
await self._client.post(
f"store/addons/{addon}/update", json=options.to_dict() if options else None
f"store/addons/{addon}/update",
json=options.to_dict() if options else None,
timeout=None,
)

async def reload(self) -> None:
Expand Down
12 changes: 10 additions & 2 deletions aiohasupervisor/supervisor.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Supervisor client for supervisor."""

from aiohttp import ClientTimeout

from .client import _SupervisorComponentClient
from .const import ResponseType
from .models.supervisor import (
Expand All @@ -15,7 +17,11 @@ class SupervisorManagementClient(_SupervisorComponentClient):

async def ping(self) -> None:
"""Check connection to supervisor."""
await self._client.get("supervisor/ping", response_type=ResponseType.NONE)
await self._client.get(
"supervisor/ping",
response_type=ResponseType.NONE,
timeout=ClientTimeout(total=15),
)

async def info(self) -> SupervisorInfo:
"""Get supervisor info."""
Expand All @@ -35,7 +41,9 @@ async def update(self, options: SupervisorUpdateOptions | None = None) -> None:
latest version and ignore that field.
"""
await self._client.post(
"supervisor/update", json=options.to_dict() if options else None
"supervisor/update",
json=options.to_dict() if options else None,
timeout=None,
)

async def reload(self) -> None:
Expand Down

0 comments on commit 0089da8

Please sign in to comment.