Skip to content
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
e1208e9
Migrate statistics to use timestamp columns
bdraco Feb 3, 2023
0b4b5b7
update queries
bdraco Feb 3, 2023
ee065e9
leave dupliate stats cleanup alone
bdraco Feb 3, 2023
4c5c6a3
leave dupliate stats cleanup alone
bdraco Feb 3, 2023
03218f8
lint
bdraco Feb 3, 2023
3f46b39
lint
bdraco Feb 3, 2023
d6f83a6
fixes
bdraco Feb 3, 2023
009c1b7
bump it
bdraco Feb 3, 2023
e32772a
fixes
bdraco Feb 3, 2023
59395e6
fixes
bdraco Feb 3, 2023
60d4ba6
fixes
bdraco Feb 3, 2023
6fd6055
Merge branch 'dev' into stats_migration
bdraco Feb 3, 2023
39a6c18
tweak language
bdraco Feb 3, 2023
5f7c96a
tweak language
bdraco Feb 3, 2023
aa6460a
fix version
bdraco Feb 3, 2023
1257a73
make sure to cleanup old indexes when we are done as well
bdraco Feb 3, 2023
05aef96
make sure to cleanup old indexes when we are done as well
bdraco Feb 3, 2023
9ad6e8b
tweak
bdraco Feb 3, 2023
bcf5dd7
drop index after cleanup
bdraco Feb 3, 2023
d8d82d3
Merge branch 'dev' into stats_migration
bdraco Feb 5, 2023
77b63e7
tweak
bdraco Feb 5, 2023
21a625c
tweak
bdraco Feb 5, 2023
dac7e4a
missing fstring
bdraco Feb 5, 2023
c0398e7
Merge branch 'dev' into stats_migration
bdraco Feb 5, 2023
cb28009
relo code to match design
bdraco Feb 5, 2023
b83babb
Merge branch 'dev' into stats_migration
bdraco Feb 6, 2023
11096ff
set the time zone to utc for the connection with mysql so we avoid th…
bdraco Feb 6, 2023
4757bca
update test
bdraco Feb 6, 2023
198068f
Merge branch 'dev' into stats_migration
bdraco Feb 7, 2023
51e4914
Merge branch 'dev' into stats_migration
bdraco Feb 7, 2023
22ff378
Merge branch 'dev' into stats_migration
bdraco Feb 7, 2023
349842e
Merge remote-tracking branch 'upstream/dev' into stats_migration
bdraco Feb 8, 2023
27dc5cb
move asserts
bdraco Feb 8, 2023
c661870
simplify math
bdraco Feb 8, 2023
0f2ae5f
Merge branch 'dev' into stats_migration
bdraco Feb 8, 2023
7212fdc
tweak
bdraco Feb 9, 2023
8d856c8
Apply suggestions from code review
bdraco Feb 9, 2023
a81167f
Update homeassistant/components/recorder/migration.py
bdraco Feb 9, 2023
1a819ef
Merge branch 'dev' into stats_migration
bdraco Feb 9, 2023
8b95851
Merge branch 'dev' into stats_migration
bdraco Feb 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 7 additions & 11 deletions homeassistant/components/recorder/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -638,10 +638,8 @@ def run(self) -> None:
else:
persistent_notification.create(
self.hass,
(
"The database migration failed, check [the logs](/config/logs)."
"Database Migration Failed"
),
"The database migration failed, check [the logs](/config/logs).",
"Database Migration Failed",
"recorder_database_migration",
)
self.hass.add_job(self.async_set_db_ready)
Expand Down Expand Up @@ -730,8 +728,10 @@ def _migrate_schema_and_setup_run(
(
"System performance will temporarily degrade during the database"
" upgrade. Do not power down or restart the system until the upgrade"
" completes. Integrations that read the database, such as logbook and"
" history, may return inconsistent results until the upgrade completes."
" completes. Integrations that read the database, such as logbook,"
" history, and statistics may return inconsistent results until the "
" upgrade completes. This notification will be automatically dismissed"
" when the upgrade completes."
),
"Database upgrade in progress",
"recorder_database_migration",
Expand Down Expand Up @@ -1027,11 +1027,7 @@ def _open_event_session(self) -> None:

def _post_schema_migration(self, old_version: int, new_version: int) -> None:
"""Run post schema migration tasks."""
assert self.engine is not None
assert self.event_session is not None
migration.post_schema_migration(
self.engine, self.event_session, old_version, new_version
)
migration.post_schema_migration(self, old_version, new_version)

def _send_keep_alive(self) -> None:
"""Send a keep alive to keep the db connection open."""
Expand Down
47 changes: 38 additions & 9 deletions homeassistant/components/recorder/db_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,12 @@
import homeassistant.util.dt as dt_util

from .const import ALL_DOMAIN_EXCLUDE_ATTRS, SupportedDialect
from .models import StatisticData, StatisticMetaData, process_timestamp
from .models import (
StatisticData,
StatisticMetaData,
datetime_to_timestamp_or_none,
process_timestamp,
)


# SQLAlchemy Schema
Expand All @@ -61,7 +66,7 @@ class Base(DeclarativeBase):
"""Base class for tables."""


SCHEMA_VERSION = 33
SCHEMA_VERSION = 35

_LOGGER = logging.getLogger(__name__)

Expand All @@ -76,6 +81,10 @@ class Base(DeclarativeBase):
TABLE_STATISTICS_RUNS = "statistics_runs"
TABLE_STATISTICS_SHORT_TERM = "statistics_short_term"

# Order is important here, as we expect statistics to have
Comment thread
bdraco marked this conversation as resolved.
Outdated
# more rows than statistics_short_term
Comment thread
bdraco marked this conversation as resolved.
Outdated
STATISTICS_TABLES = ("statistics", "statistics_short_term")
Comment thread
bdraco marked this conversation as resolved.
Outdated

MAX_STATE_ATTRS_BYTES = 16384
PSQL_DIALECT = SupportedDialect.POSTGRESQL

Expand Down Expand Up @@ -502,17 +511,24 @@ class StatisticsBase:
"""Statistics base class."""

id: Mapped[int] = mapped_column(Integer, Identity(), primary_key=True)
created: Mapped[datetime] = mapped_column(DATETIME_TYPE, default=dt_util.utcnow)
created: Mapped[datetime] = mapped_column(
DATETIME_TYPE, default=dt_util.utcnow
) # No longer used
created_ts: Mapped[float] = mapped_column(TIMESTAMP_TYPE, default=time.time)
metadata_id: Mapped[int | None] = mapped_column(
Integer,
ForeignKey(f"{TABLE_STATISTICS_META}.id", ondelete="CASCADE"),
index=True,
)
start: Mapped[datetime | None] = mapped_column(DATETIME_TYPE, index=True)
start: Mapped[datetime | None] = mapped_column(
DATETIME_TYPE, index=True
) # No longer used
start_ts: Mapped[float | None] = mapped_column(TIMESTAMP_TYPE, index=True)
mean: Mapped[float | None] = mapped_column(DOUBLE_TYPE)
min: Mapped[float | None] = mapped_column(DOUBLE_TYPE)
max: Mapped[float | None] = mapped_column(DOUBLE_TYPE)
last_reset: Mapped[datetime | None] = mapped_column(DATETIME_TYPE)
last_reset_ts: Mapped[float | None] = mapped_column(TIMESTAMP_TYPE)
state: Mapped[float | None] = mapped_column(DOUBLE_TYPE)
sum: Mapped[float | None] = mapped_column(DOUBLE_TYPE)

Expand All @@ -521,9 +537,17 @@ class StatisticsBase:
@classmethod
def from_stats(cls, metadata_id: int, stats: StatisticData) -> Self:
"""Create object from a statistics."""
return cls( # type: ignore[call-arg,misc]
return cls( # type: ignore[call-arg]
metadata_id=metadata_id,
**stats,
start=None,
start_ts=dt_util.utc_to_timestamp(stats["start"]),
mean=stats.get("mean"),
min=stats.get("min"),
max=stats.get("max"),
last_reset=None,
last_reset_ts=datetime_to_timestamp_or_none(stats.get("last_reset")),
state=stats.get("state"),
sum=stats.get("sum"),
)


Expand All @@ -534,7 +558,12 @@ class Statistics(Base, StatisticsBase):

__table_args__ = (
# Used for fetching statistics for a certain entity at a specific time
Index("ix_statistics_statistic_id_start", "metadata_id", "start", unique=True),
Index(
"ix_statistics_statistic_id_start_ts",
"metadata_id",
"start_ts",
unique=True,
),
)
__tablename__ = TABLE_STATISTICS

Expand All @@ -547,9 +576,9 @@ class StatisticsShortTerm(Base, StatisticsBase):
__table_args__ = (
# Used for fetching statistics for a certain entity at a specific time
Index(
"ix_statistics_short_term_statistic_id_start",
"ix_statistics_short_term_statistic_id_start_ts",
"metadata_id",
"start",
"start_ts",
unique=True,
),
)
Expand Down
Loading