Improve http2 task handling for Alexa Devices (#172649)

This commit is contained in:
jameson_uk
2026-06-01 12:11:29 +02:00
committed by GitHub
parent 6bb027f008
commit 7a32cdc250
3 changed files with 59 additions and 15 deletions
@@ -1,8 +1,5 @@
"""Alexa Devices integration."""
import asyncio
import contextlib
from homeassistant.const import CONF_COUNTRY, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import aiohttp_client, config_validation as cv, httpx_client
@@ -46,21 +43,17 @@ async def async_setup_entry(hass: HomeAssistant, entry: AmazonConfigEntry) -> bo
async def _on_http2_reauth_required() -> None:
entry.async_start_reauth(hass)
async def _cancel_http2() -> None:
http2_task.cancel()
with contextlib.suppress(asyncio.CancelledError):
await http2_task
alexa_httpx_client = httpx_client.get_async_client(
hass,
alpn_protocols=SSL_ALPN_HTTP11_HTTP2,
)
http2_task = await coordinator.api.start_http2_processing(
alexa_httpx_client, on_reauth_required=_on_http2_reauth_required
await coordinator.api.start_http2_processing(
alexa_httpx_client,
on_reauth_required=_on_http2_reauth_required,
)
entry.async_on_unload(_cancel_http2)
entry.async_on_unload(coordinator.api.stop_http2_processing)
entry.runtime_data = coordinator
+9 -3
View File
@@ -65,9 +65,15 @@ def mock_amazon_devices_client() -> Generator[AsyncMock]:
client.on_history_event = MagicMock()
client.on_volume_state_event = MagicMock()
client.on_media_state_event = MagicMock()
http2_task = asyncio.Future()
http2_task.set_result(None)
client.start_http2_processing = AsyncMock(return_value=http2_task)
async def _start_http2_processing(*_args, **_kwargs) -> asyncio.Task[None]:
async def _completed_task() -> None:
return
return asyncio.create_task(_completed_task())
client.start_http2_processing = AsyncMock(side_effect=_start_http2_processing)
client.stop_http2_processing = AsyncMock()
client.send_sound_notification = AsyncMock()
yield client
+46 -1
View File
@@ -1,6 +1,7 @@
"""Tests for the Alexa Devices integration."""
from unittest.mock import AsyncMock
import asyncio
from unittest.mock import AsyncMock, patch
import pytest
from syrupy.assertion import SnapshotAssertion
@@ -160,3 +161,47 @@ async def test_http2_reauth_required(
flows = hass.config_entries.flow.async_progress()
assert len(flows) == 1
assert flows[0]["context"]["source"] == "reauth"
async def test_http2_reauth_callback_triggers_reauth(
hass: HomeAssistant,
mock_amazon_devices_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test on_reauth_required callback passed to start_http2_processing triggers reauth."""
captured_callback = None
http2_task: asyncio.Task | None = None
async def capture_callback(_client, on_reauth_required=None) -> asyncio.Task:
nonlocal captured_callback, http2_task
captured_callback = on_reauth_required
http2_task = hass.loop.create_task(asyncio.sleep(3600))
return http2_task
mock_amazon_devices_client.start_http2_processing.side_effect = capture_callback
with patch.object(mock_config_entry, "async_start_reauth") as mock_reauth:
await setup_integration(hass, mock_config_entry)
assert captured_callback is not None
await captured_callback()
mock_reauth.assert_called_once_with(hass)
assert http2_task is not None
http2_task.cancel()
await asyncio.gather(http2_task, return_exceptions=True)
async def test_http2_stop_processing_called_on_unload(
hass: HomeAssistant,
mock_amazon_devices_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test stop_http2_processing is called on unload."""
await setup_integration(hass, mock_config_entry)
await hass.config_entries.async_unload(mock_config_entry.entry_id)
await hass.async_block_till_done()
mock_amazon_devices_client.stop_http2_processing.assert_awaited_once()