Ensure recorder runs are cleaned up during purge (#36989)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>pull/37017/head
parent
b4489e132c
commit
ad6315be5c
|
@ -6,7 +6,7 @@ from sqlalchemy.exc import SQLAlchemyError
|
|||
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from .models import Events, States
|
||||
from .models import Events, RecorderRuns, States
|
||||
from .util import session_scope
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -33,6 +33,13 @@ def purge_old_data(instance, purge_days, repack):
|
|||
)
|
||||
_LOGGER.debug("Deleted %s events", deleted_rows)
|
||||
|
||||
deleted_rows = (
|
||||
session.query(RecorderRuns)
|
||||
.filter(RecorderRuns.start < purge_before)
|
||||
.delete(synchronize_session=False)
|
||||
)
|
||||
_LOGGER.debug("Deleted %s recorder_runs", deleted_rows)
|
||||
|
||||
if repack:
|
||||
# Execute sqlite or postgresql vacuum command to free up space on disk
|
||||
if instance.engine.driver in ("pysqlite", "postgresql"):
|
||||
|
@ -41,7 +48,7 @@ def purge_old_data(instance, purge_days, repack):
|
|||
# Optimize mysql / mariadb tables to free up space on disk
|
||||
elif instance.engine.driver == "mysqldb":
|
||||
_LOGGER.debug("Optimizing SQL DB to free space")
|
||||
instance.engine.execute("OPTIMIZE TABLE states, events")
|
||||
instance.engine.execute("OPTIMIZE TABLE states, events, recorder_runs")
|
||||
|
||||
except SQLAlchemyError as err:
|
||||
_LOGGER.warning("Error purging history: %s.", err)
|
||||
|
|
|
@ -5,9 +5,10 @@ import unittest
|
|||
|
||||
from homeassistant.components import recorder
|
||||
from homeassistant.components.recorder.const import DATA_INSTANCE
|
||||
from homeassistant.components.recorder.models import Events, States
|
||||
from homeassistant.components.recorder.models import Events, RecorderRuns, States
|
||||
from homeassistant.components.recorder.purge import purge_old_data
|
||||
from homeassistant.components.recorder.util import session_scope
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from tests.async_mock import patch
|
||||
from tests.common import get_test_home_assistant, init_recorder_component
|
||||
|
@ -94,6 +95,32 @@ class TestRecorderPurge(unittest.TestCase):
|
|||
)
|
||||
)
|
||||
|
||||
def _add_test_recorder_runs(self):
|
||||
"""Add a few recorder_runs for testing."""
|
||||
now = datetime.now()
|
||||
five_days_ago = now - timedelta(days=5)
|
||||
eleven_days_ago = now - timedelta(days=11)
|
||||
|
||||
self.hass.block_till_done()
|
||||
self.hass.data[DATA_INSTANCE].block_till_done()
|
||||
|
||||
with recorder.session_scope(hass=self.hass) as session:
|
||||
for rec_id in range(6):
|
||||
if rec_id < 2:
|
||||
timestamp = eleven_days_ago
|
||||
elif rec_id < 4:
|
||||
timestamp = five_days_ago
|
||||
else:
|
||||
timestamp = now
|
||||
|
||||
session.add(
|
||||
RecorderRuns(
|
||||
start=timestamp,
|
||||
created=dt_util.utcnow(),
|
||||
end=timestamp + timedelta(days=1),
|
||||
)
|
||||
)
|
||||
|
||||
def test_purge_old_states(self):
|
||||
"""Test deleting old states."""
|
||||
self._add_test_states()
|
||||
|
@ -127,6 +154,7 @@ class TestRecorderPurge(unittest.TestCase):
|
|||
service_data = {"keep_days": 4}
|
||||
self._add_test_events()
|
||||
self._add_test_states()
|
||||
self._add_test_recorder_runs()
|
||||
|
||||
# make sure we start with 6 states
|
||||
with session_scope(hass=self.hass) as session:
|
||||
|
@ -136,6 +164,9 @@ class TestRecorderPurge(unittest.TestCase):
|
|||
events = session.query(Events).filter(Events.event_type.like("EVENT_TEST%"))
|
||||
assert events.count() == 6
|
||||
|
||||
recorder_runs = session.query(RecorderRuns)
|
||||
assert recorder_runs.count() == 7
|
||||
|
||||
self.hass.data[DATA_INSTANCE].block_till_done()
|
||||
|
||||
# run purge method - no service data, use defaults
|
||||
|
@ -162,6 +193,9 @@ class TestRecorderPurge(unittest.TestCase):
|
|||
# now we should only have 2 events left
|
||||
assert events.count() == 2
|
||||
|
||||
# now we should only have 3 recorder runs left
|
||||
assert recorder_runs.count() == 3
|
||||
|
||||
assert not (
|
||||
"EVENT_TEST_PURGE" in (event.event_type for event in events.all())
|
||||
)
|
||||
|
@ -175,6 +209,6 @@ class TestRecorderPurge(unittest.TestCase):
|
|||
self.hass.block_till_done()
|
||||
self.hass.data[DATA_INSTANCE].block_till_done()
|
||||
assert (
|
||||
mock_logger.debug.mock_calls[3][1][0]
|
||||
mock_logger.debug.mock_calls[4][1][0]
|
||||
== "Vacuuming SQL DB to free space"
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue