Skip to content

Commit 2ef81a5

Browse files
Allow backups to report the upload progress (#163608)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
1 parent ce61548 commit 2ef81a5

File tree

20 files changed

+147
-5
lines changed

20 files changed

+147
-5
lines changed

homeassistant/components/aws_s3/backup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
BackupAgent,
1515
BackupAgentError,
1616
BackupNotFound,
17+
OnProgressCallback,
1718
suggested_filename,
1819
)
1920
from homeassistant.core import HomeAssistant, callback
@@ -132,6 +133,7 @@ async def async_upload_backup(
132133
*,
133134
open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]],
134135
backup: AgentBackup,
136+
on_progress: OnProgressCallback,
135137
**kwargs: Any,
136138
) -> None:
137139
"""Upload a backup.

homeassistant/components/azure_storage/backup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
BackupAgent,
1717
BackupAgentError,
1818
BackupNotFound,
19+
OnProgressCallback,
1920
suggested_filename,
2021
)
2122
from homeassistant.core import HomeAssistant, callback
@@ -129,6 +130,7 @@ async def async_upload_backup(
129130
*,
130131
open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]],
131132
backup: AgentBackup,
133+
on_progress: OnProgressCallback,
132134
**kwargs: Any,
133135
) -> None:
134136
"""Upload a backup."""

homeassistant/components/backblaze_b2/backup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
BackupAgent,
1818
BackupAgentError,
1919
BackupNotFound,
20+
OnProgressCallback,
2021
suggested_filename,
2122
)
2223
from homeassistant.core import HomeAssistant, callback
@@ -230,6 +231,7 @@ async def async_upload_backup(
230231
*,
231232
open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]],
232233
backup: AgentBackup,
234+
on_progress: OnProgressCallback,
233235
**kwargs: Any,
234236
) -> None:
235237
"""Upload a backup to Backblaze B2.

homeassistant/components/backup/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
BackupAgentError,
1818
BackupAgentPlatformProtocol,
1919
LocalBackupAgent,
20+
OnProgressCallback,
2021
)
2122
from .config import BackupConfig, CreateBackupParametersDict
2223
from .const import DATA_MANAGER, DOMAIN
@@ -41,6 +42,7 @@
4142
RestoreBackupEvent,
4243
RestoreBackupStage,
4344
RestoreBackupState,
45+
UploadBackupEvent,
4446
WrittenBackup,
4547
)
4648
from .models import AddonInfo, AgentBackup, BackupNotFound, Folder
@@ -72,9 +74,11 @@
7274
"LocalBackupAgent",
7375
"ManagerBackup",
7476
"NewBackup",
77+
"OnProgressCallback",
7578
"RestoreBackupEvent",
7679
"RestoreBackupStage",
7780
"RestoreBackupState",
81+
"UploadBackupEvent",
7882
"WrittenBackup",
7983
"async_get_manager",
8084
"suggested_filename",

homeassistant/components/backup/agent.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@
1414
from .models import AgentBackup, BackupAgentError
1515

1616

17+
class OnProgressCallback(Protocol):
18+
"""Protocol for on_progress callback."""
19+
20+
def __call__(self, *, bytes_uploaded: int, **kwargs: Any) -> None:
21+
"""Report upload progress."""
22+
23+
1724
class BackupAgentUnreachableError(BackupAgentError):
1825
"""Raised when the agent can't reach its API."""
1926

@@ -53,12 +60,14 @@ async def async_upload_backup(
5360
*,
5461
open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]],
5562
backup: AgentBackup,
63+
on_progress: OnProgressCallback,
5664
**kwargs: Any,
5765
) -> None:
5866
"""Upload a backup.
5967
6068
:param open_stream: A function returning an async iterator that yields bytes.
6169
:param backup: Metadata about the backup that should be uploaded.
70+
:param on_progress: A callback to report the number of uploaded bytes.
6271
"""
6372

6473
@abc.abstractmethod

homeassistant/components/backup/backup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from homeassistant.core import HomeAssistant
1212
from homeassistant.helpers.hassio import is_hassio
1313

14-
from .agent import BackupAgent, LocalBackupAgent
14+
from .agent import BackupAgent, LocalBackupAgent, OnProgressCallback
1515
from .const import DOMAIN, LOGGER
1616
from .models import AgentBackup, BackupNotFound
1717
from .util import read_backup, suggested_filename
@@ -73,6 +73,7 @@ async def async_upload_backup(
7373
*,
7474
open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]],
7575
backup: AgentBackup,
76+
on_progress: OnProgressCallback,
7677
**kwargs: Any,
7778
) -> None:
7879
"""Upload a backup."""

homeassistant/components/backup/manager.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,15 @@ class BlockedEvent(ManagerStateEvent):
252252
manager_state: BackupManagerState = BackupManagerState.BLOCKED
253253

254254

255+
@dataclass(frozen=True, kw_only=True, slots=True)
256+
class UploadBackupEvent(ManagerStateEvent):
257+
"""Backup agent upload progress event."""
258+
259+
agent_id: str
260+
uploaded_bytes: int
261+
total_bytes: int
262+
263+
255264
class BackupPlatformProtocol(Protocol):
256265
"""Define the format that backup platforms can have."""
257266

@@ -579,9 +588,24 @@ async def upload_backup_to_agent(agent_id: str) -> None:
579588
_backup = replace(
580589
backup, protected=should_encrypt, size=streamer.size()
581590
)
582-
await self.backup_agents[agent_id].async_upload_backup(
591+
agent = self.backup_agents[agent_id]
592+
593+
@callback
594+
def on_upload_progress(*, bytes_uploaded: int, **kwargs: Any) -> None:
595+
"""Handle upload progress."""
596+
self.async_on_backup_event(
597+
UploadBackupEvent(
598+
manager_state=self.state,
599+
agent_id=agent_id,
600+
uploaded_bytes=bytes_uploaded,
601+
total_bytes=_backup.size,
602+
)
603+
)
604+
605+
await agent.async_upload_backup(
583606
open_stream=open_stream_func,
584607
backup=_backup,
608+
on_progress=on_upload_progress,
585609
)
586610
if streamer:
587611
await streamer.wait()
@@ -1374,9 +1398,10 @@ def async_on_backup_event(
13741398
"""Forward event to subscribers."""
13751399
if (current_state := self.state) != (new_state := event.manager_state):
13761400
LOGGER.debug("Backup state: %s -> %s", current_state, new_state)
1377-
self.last_event = event
1378-
if not isinstance(event, (BlockedEvent, IdleEvent)):
1379-
self.last_action_event = event
1401+
if not isinstance(event, UploadBackupEvent):
1402+
self.last_event = event
1403+
if not isinstance(event, (BlockedEvent, IdleEvent)):
1404+
self.last_action_event = event
13801405
for subscription in self._backup_event_subscriptions:
13811406
subscription(event)
13821407

homeassistant/components/cloud/backup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
BackupAgent,
1919
BackupAgentError,
2020
BackupNotFound,
21+
OnProgressCallback,
2122
)
2223
from homeassistant.core import HomeAssistant, callback
2324
from homeassistant.helpers.aiohttp_client import ChunkAsyncStreamIterator
@@ -106,6 +107,7 @@ async def async_upload_backup(
106107
*,
107108
open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]],
108109
backup: AgentBackup,
110+
on_progress: OnProgressCallback,
109111
**kwargs: Any,
110112
) -> None:
111113
"""Upload a backup.

homeassistant/components/cloudflare_r2/backup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
BackupAgent,
1515
BackupAgentError,
1616
BackupNotFound,
17+
OnProgressCallback,
1718
suggested_filename,
1819
)
1920
from homeassistant.core import HomeAssistant, callback
@@ -129,6 +130,7 @@ async def async_upload_backup(
129130
*,
130131
open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]],
131132
backup: AgentBackup,
133+
on_progress: OnProgressCallback,
132134
**kwargs: Any,
133135
) -> None:
134136
"""Upload a backup.

homeassistant/components/google_drive/backup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
BackupAgent,
1414
BackupAgentError,
1515
BackupNotFound,
16+
OnProgressCallback,
1617
)
1718
from homeassistant.core import HomeAssistant, callback
1819
from homeassistant.exceptions import HomeAssistantError
@@ -75,6 +76,7 @@ async def async_upload_backup(
7576
*,
7677
open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]],
7778
backup: AgentBackup,
79+
on_progress: OnProgressCallback,
7880
**kwargs: Any,
7981
) -> None:
8082
"""Upload a backup.

0 commit comments

Comments
 (0)