mirror of
https://github.com/home-assistant/core.git
synced 2026-09-27 18:08:37 -04:00
Auto repack the database on the second sunday of the month (#69314)
This commit is contained in:
@@ -12,6 +12,7 @@ from sqlalchemy.exc import DatabaseError, OperationalError, SQLAlchemyError
|
||||
from homeassistant.components import recorder
|
||||
from homeassistant.components.recorder import (
|
||||
CONF_AUTO_PURGE,
|
||||
CONF_AUTO_REPACK,
|
||||
CONF_DB_URL,
|
||||
CONFIG_SCHEMA,
|
||||
DOMAIN,
|
||||
@@ -70,6 +71,7 @@ def _default_recorder(hass):
|
||||
return Recorder(
|
||||
hass,
|
||||
auto_purge=True,
|
||||
auto_repack=True,
|
||||
keep_days=7,
|
||||
commit_interval=1,
|
||||
uri="sqlite://",
|
||||
@@ -627,6 +629,7 @@ async def test_defaults_set(hass):
|
||||
assert recorder_config is not None
|
||||
# pylint: disable=unsubscriptable-object
|
||||
assert recorder_config["auto_purge"]
|
||||
assert recorder_config["auto_repack"]
|
||||
assert recorder_config["purge_keep_days"] == 10
|
||||
|
||||
|
||||
@@ -695,6 +698,120 @@ def test_auto_purge(hass_recorder):
|
||||
dt_util.set_default_time_zone(original_tz)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("enable_nightly_purge", [True])
|
||||
def test_auto_purge_auto_repack_on_second_sunday(hass_recorder):
|
||||
"""Test periodic purge scheduling does a repack on the 2nd sunday."""
|
||||
hass = hass_recorder()
|
||||
|
||||
original_tz = dt_util.DEFAULT_TIME_ZONE
|
||||
|
||||
tz = dt_util.get_time_zone("Europe/Copenhagen")
|
||||
dt_util.set_default_time_zone(tz)
|
||||
|
||||
# Purging is scheduled to happen at 4:12am every day. Exercise this behavior by
|
||||
# firing time changed events and advancing the clock around this time. Pick an
|
||||
# arbitrary year in the future to avoid boundary conditions relative to the current
|
||||
# date.
|
||||
#
|
||||
# The clock is started at 4:15am then advanced forward below
|
||||
now = dt_util.utcnow()
|
||||
test_time = datetime(now.year + 2, 1, 1, 4, 15, 0, tzinfo=tz)
|
||||
run_tasks_at_time(hass, test_time)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.recorder.is_second_sunday", return_value=True
|
||||
), patch(
|
||||
"homeassistant.components.recorder.purge.purge_old_data", return_value=True
|
||||
) as purge_old_data, patch(
|
||||
"homeassistant.components.recorder.perodic_db_cleanups"
|
||||
) as perodic_db_cleanups:
|
||||
# Advance one day, and the purge task should run
|
||||
test_time = test_time + timedelta(days=1)
|
||||
run_tasks_at_time(hass, test_time)
|
||||
assert len(purge_old_data.mock_calls) == 1
|
||||
args, _ = purge_old_data.call_args_list[0]
|
||||
assert args[2] is True # repack
|
||||
assert len(perodic_db_cleanups.mock_calls) == 1
|
||||
|
||||
dt_util.set_default_time_zone(original_tz)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("enable_nightly_purge", [True])
|
||||
def test_auto_purge_auto_repack_disabled_on_second_sunday(hass_recorder):
|
||||
"""Test periodic purge scheduling does not auto repack on the 2nd sunday if disabled."""
|
||||
hass = hass_recorder({CONF_AUTO_REPACK: False})
|
||||
|
||||
original_tz = dt_util.DEFAULT_TIME_ZONE
|
||||
|
||||
tz = dt_util.get_time_zone("Europe/Copenhagen")
|
||||
dt_util.set_default_time_zone(tz)
|
||||
|
||||
# Purging is scheduled to happen at 4:12am every day. Exercise this behavior by
|
||||
# firing time changed events and advancing the clock around this time. Pick an
|
||||
# arbitrary year in the future to avoid boundary conditions relative to the current
|
||||
# date.
|
||||
#
|
||||
# The clock is started at 4:15am then advanced forward below
|
||||
now = dt_util.utcnow()
|
||||
test_time = datetime(now.year + 2, 1, 1, 4, 15, 0, tzinfo=tz)
|
||||
run_tasks_at_time(hass, test_time)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.recorder.is_second_sunday", return_value=True
|
||||
), patch(
|
||||
"homeassistant.components.recorder.purge.purge_old_data", return_value=True
|
||||
) as purge_old_data, patch(
|
||||
"homeassistant.components.recorder.perodic_db_cleanups"
|
||||
) as perodic_db_cleanups:
|
||||
# Advance one day, and the purge task should run
|
||||
test_time = test_time + timedelta(days=1)
|
||||
run_tasks_at_time(hass, test_time)
|
||||
assert len(purge_old_data.mock_calls) == 1
|
||||
args, _ = purge_old_data.call_args_list[0]
|
||||
assert args[2] is False # repack
|
||||
assert len(perodic_db_cleanups.mock_calls) == 1
|
||||
|
||||
dt_util.set_default_time_zone(original_tz)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("enable_nightly_purge", [True])
|
||||
def test_auto_purge_no_auto_repack_on_not_second_sunday(hass_recorder):
|
||||
"""Test periodic purge scheduling does not do a repack unless its the 2nd sunday."""
|
||||
hass = hass_recorder()
|
||||
|
||||
original_tz = dt_util.DEFAULT_TIME_ZONE
|
||||
|
||||
tz = dt_util.get_time_zone("Europe/Copenhagen")
|
||||
dt_util.set_default_time_zone(tz)
|
||||
|
||||
# Purging is scheduled to happen at 4:12am every day. Exercise this behavior by
|
||||
# firing time changed events and advancing the clock around this time. Pick an
|
||||
# arbitrary year in the future to avoid boundary conditions relative to the current
|
||||
# date.
|
||||
#
|
||||
# The clock is started at 4:15am then advanced forward below
|
||||
now = dt_util.utcnow()
|
||||
test_time = datetime(now.year + 2, 1, 1, 4, 15, 0, tzinfo=tz)
|
||||
run_tasks_at_time(hass, test_time)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.recorder.is_second_sunday", return_value=False
|
||||
), patch(
|
||||
"homeassistant.components.recorder.purge.purge_old_data", return_value=True
|
||||
) as purge_old_data, patch(
|
||||
"homeassistant.components.recorder.perodic_db_cleanups"
|
||||
) as perodic_db_cleanups:
|
||||
# Advance one day, and the purge task should run
|
||||
test_time = test_time + timedelta(days=1)
|
||||
run_tasks_at_time(hass, test_time)
|
||||
assert len(purge_old_data.mock_calls) == 1
|
||||
args, _ = purge_old_data.call_args_list[0]
|
||||
assert args[2] is False # repack
|
||||
assert len(perodic_db_cleanups.mock_calls) == 1
|
||||
|
||||
dt_util.set_default_time_zone(original_tz)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("enable_nightly_purge", [True])
|
||||
def test_auto_purge_disabled(hass_recorder):
|
||||
"""Test periodic db cleanup still run when auto purge is disabled."""
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""Test util methods."""
|
||||
from datetime import timedelta
|
||||
from datetime import datetime, timedelta
|
||||
import os
|
||||
import sqlite3
|
||||
from unittest.mock import MagicMock, patch
|
||||
@@ -12,7 +12,11 @@ from homeassistant.components import recorder
|
||||
from homeassistant.components.recorder import run_information_with_session, util
|
||||
from homeassistant.components.recorder.const import DATA_INSTANCE, SQLITE_URL_PREFIX
|
||||
from homeassistant.components.recorder.models import RecorderRuns
|
||||
from homeassistant.components.recorder.util import end_incomplete_runs, session_scope
|
||||
from homeassistant.components.recorder.util import (
|
||||
end_incomplete_runs,
|
||||
is_second_sunday,
|
||||
session_scope,
|
||||
)
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from .common import corrupt_db_file
|
||||
@@ -584,3 +588,14 @@ async def test_write_lock_db(hass, tmp_path):
|
||||
# would be allowed to proceed as the goal is to prevent
|
||||
# all the other threads from accessing the database
|
||||
await hass.async_add_executor_job(_drop_table)
|
||||
|
||||
|
||||
def test_is_second_sunday():
|
||||
"""Test we can find the second sunday of the month."""
|
||||
assert is_second_sunday(datetime(2022, 1, 9, 0, 0, 0, tzinfo=dt_util.UTC)) is True
|
||||
assert is_second_sunday(datetime(2022, 2, 13, 0, 0, 0, tzinfo=dt_util.UTC)) is True
|
||||
assert is_second_sunday(datetime(2022, 3, 13, 0, 0, 0, tzinfo=dt_util.UTC)) is True
|
||||
assert is_second_sunday(datetime(2022, 4, 10, 0, 0, 0, tzinfo=dt_util.UTC)) is True
|
||||
assert is_second_sunday(datetime(2022, 5, 8, 0, 0, 0, tzinfo=dt_util.UTC)) is True
|
||||
|
||||
assert is_second_sunday(datetime(2022, 1, 10, 0, 0, 0, tzinfo=dt_util.UTC)) is False
|
||||
|
||||
Reference in New Issue
Block a user