1
mirror of https://github.com/home-assistant/core synced 2024-08-02 23:40:32 +02:00

RFC - Add a 3rd state to the HA shutdown sequence for writing… (#33358)

* add third stage to hass shutdown

* use 3rd stage in storage

* update core state

* add writing data to multi stop ignore

* update core test

* review comment

* update name based on feedback
This commit is contained in:
David F. Mulcahey 2020-03-30 13:18:39 -04:00 committed by GitHub
parent 01bf4daf37
commit bcd1eb952c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 27 additions and 8 deletions

View File

@ -184,6 +184,7 @@ EVENT_CORE_CONFIG_UPDATE = "core_config_updated"
EVENT_HOMEASSISTANT_CLOSE = "homeassistant_close" EVENT_HOMEASSISTANT_CLOSE = "homeassistant_close"
EVENT_HOMEASSISTANT_START = "homeassistant_start" EVENT_HOMEASSISTANT_START = "homeassistant_start"
EVENT_HOMEASSISTANT_STOP = "homeassistant_stop" EVENT_HOMEASSISTANT_STOP = "homeassistant_stop"
EVENT_HOMEASSISTANT_FINAL_WRITE = "homeassistant_final_write"
EVENT_LOGBOOK_ENTRY = "logbook_entry" EVENT_LOGBOOK_ENTRY = "logbook_entry"
EVENT_PLATFORM_DISCOVERED = "platform_discovered" EVENT_PLATFORM_DISCOVERED = "platform_discovered"
EVENT_SCRIPT_STARTED = "script_started" EVENT_SCRIPT_STARTED = "script_started"

View File

@ -47,6 +47,7 @@ from homeassistant.const import (
EVENT_CALL_SERVICE, EVENT_CALL_SERVICE,
EVENT_CORE_CONFIG_UPDATE, EVENT_CORE_CONFIG_UPDATE,
EVENT_HOMEASSISTANT_CLOSE, EVENT_HOMEASSISTANT_CLOSE,
EVENT_HOMEASSISTANT_FINAL_WRITE,
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STOP, EVENT_HOMEASSISTANT_STOP,
EVENT_SERVICE_REGISTERED, EVENT_SERVICE_REGISTERED,
@ -151,6 +152,7 @@ class CoreState(enum.Enum):
starting = "STARTING" starting = "STARTING"
running = "RUNNING" running = "RUNNING"
stopping = "STOPPING" stopping = "STOPPING"
writing_data = "WRITING_DATA"
def __str__(self) -> str: def __str__(self) -> str:
"""Return the event.""" """Return the event."""
@ -412,7 +414,7 @@ class HomeAssistant:
# regardless of the state of the loop. # regardless of the state of the loop.
if self.state == CoreState.not_running: # just ignore if self.state == CoreState.not_running: # just ignore
return return
if self.state == CoreState.stopping: if self.state == CoreState.stopping or self.state == CoreState.writing_data:
_LOGGER.info("async_stop called twice: ignored") _LOGGER.info("async_stop called twice: ignored")
return return
if self.state == CoreState.starting: if self.state == CoreState.starting:
@ -426,6 +428,11 @@ class HomeAssistant:
await self.async_block_till_done() await self.async_block_till_done()
# stage 2 # stage 2
self.state = CoreState.writing_data
self.bus.async_fire(EVENT_HOMEASSISTANT_FINAL_WRITE)
await self.async_block_till_done()
# stage 3
self.state = CoreState.not_running self.state = CoreState.not_running
self.bus.async_fire(EVENT_HOMEASSISTANT_CLOSE) self.bus.async_fire(EVENT_HOMEASSISTANT_CLOSE)
await self.async_block_till_done() await self.async_block_till_done()

View File

@ -4,7 +4,10 @@ from datetime import datetime, timedelta
import logging import logging
from typing import Any, Awaitable, Dict, List, Optional, Set, cast from typing import Any, Awaitable, Dict, List, Optional, Set, cast
from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP from homeassistant.const import (
EVENT_HOMEASSISTANT_FINAL_WRITE,
EVENT_HOMEASSISTANT_START,
)
from homeassistant.core import ( from homeassistant.core import (
CoreState, CoreState,
HomeAssistant, HomeAssistant,
@ -184,7 +187,9 @@ class RestoreStateData:
async_track_time_interval(self.hass, _async_dump_states, STATE_DUMP_INTERVAL) async_track_time_interval(self.hass, _async_dump_states, STATE_DUMP_INTERVAL)
# Dump states when stopping hass # Dump states when stopping hass
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _async_dump_states) self.hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_FINAL_WRITE, _async_dump_states
)
@callback @callback
def async_restore_entity_added(self, entity_id: str) -> None: def async_restore_entity_added(self, entity_id: str) -> None:

View File

@ -5,7 +5,7 @@ import logging
import os import os
from typing import Any, Callable, Dict, List, Optional, Type, Union from typing import Any, Callable, Dict, List, Optional, Type, Union
from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.const import EVENT_HOMEASSISTANT_FINAL_WRITE
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
from homeassistant.helpers.event import async_call_later from homeassistant.helpers.event import async_call_later
from homeassistant.loader import bind_hass from homeassistant.loader import bind_hass
@ -153,7 +153,7 @@ class Store:
"""Ensure that we write if we quit before delay has passed.""" """Ensure that we write if we quit before delay has passed."""
if self._unsub_stop_listener is None: if self._unsub_stop_listener is None:
self._unsub_stop_listener = self.hass.bus.async_listen_once( self._unsub_stop_listener = self.hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_STOP, self._async_callback_stop_write EVENT_HOMEASSISTANT_FINAL_WRITE, self._async_callback_stop_write
) )
@callback @callback

View File

@ -6,7 +6,7 @@ from unittest.mock import Mock, patch
import pytest import pytest
from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.const import EVENT_HOMEASSISTANT_FINAL_WRITE
from homeassistant.helpers import storage from homeassistant.helpers import storage
from homeassistant.util import dt from homeassistant.util import dt
@ -85,7 +85,7 @@ async def test_saving_on_stop(hass, hass_storage):
store.async_delay_save(lambda: MOCK_DATA, 1) store.async_delay_save(lambda: MOCK_DATA, 1)
assert store.key not in hass_storage assert store.key not in hass_storage
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP) hass.bus.async_fire(EVENT_HOMEASSISTANT_FINAL_WRITE)
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass_storage[store.key] == { assert hass_storage[store.key] == {
"version": MOCK_VERSION, "version": MOCK_VERSION,

View File

@ -21,6 +21,7 @@ from homeassistant.const import (
EVENT_CALL_SERVICE, EVENT_CALL_SERVICE,
EVENT_CORE_CONFIG_UPDATE, EVENT_CORE_CONFIG_UPDATE,
EVENT_HOMEASSISTANT_CLOSE, EVENT_HOMEASSISTANT_CLOSE,
EVENT_HOMEASSISTANT_FINAL_WRITE,
EVENT_HOMEASSISTANT_STOP, EVENT_HOMEASSISTANT_STOP,
EVENT_SERVICE_REGISTERED, EVENT_SERVICE_REGISTERED,
EVENT_SERVICE_REMOVED, EVENT_SERVICE_REMOVED,
@ -151,10 +152,14 @@ def test_stage_shutdown():
"""Simulate a shutdown, test calling stuff.""" """Simulate a shutdown, test calling stuff."""
hass = get_test_home_assistant() hass = get_test_home_assistant()
test_stop = [] test_stop = []
test_final_write = []
test_close = [] test_close = []
test_all = [] test_all = []
hass.bus.listen(EVENT_HOMEASSISTANT_STOP, lambda event: test_stop.append(event)) hass.bus.listen(EVENT_HOMEASSISTANT_STOP, lambda event: test_stop.append(event))
hass.bus.listen(
EVENT_HOMEASSISTANT_FINAL_WRITE, lambda event: test_final_write.append(event)
)
hass.bus.listen(EVENT_HOMEASSISTANT_CLOSE, lambda event: test_close.append(event)) hass.bus.listen(EVENT_HOMEASSISTANT_CLOSE, lambda event: test_close.append(event))
hass.bus.listen("*", lambda event: test_all.append(event)) hass.bus.listen("*", lambda event: test_all.append(event))
@ -162,7 +167,8 @@ def test_stage_shutdown():
assert len(test_stop) == 1 assert len(test_stop) == 1
assert len(test_close) == 1 assert len(test_close) == 1
assert len(test_all) == 1 assert len(test_final_write) == 1
assert len(test_all) == 2
class TestHomeAssistant(unittest.TestCase): class TestHomeAssistant(unittest.TestCase):