Reduce overhead to compile statistics (#106927)

* Reduce overhead to compile statistics

statistics uses LazyState for compatibility with State when pulling
data from the database.

After the previous round of refactoring to modern history, the setters
are never called and can be removed.

* reduce
This commit is contained in:
J. Nick Koston 2024-01-07 17:36:49 -10:00 committed by GitHub
parent d04e2d56da
commit acf78664e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 71 deletions

View file

@ -3,7 +3,7 @@ from __future__ import annotations
from datetime import datetime
import logging
from typing import Any
from typing import TYPE_CHECKING, Any
from sqlalchemy.engine.row import Row
@ -17,10 +17,16 @@ from homeassistant.core import Context, State
import homeassistant.util.dt as dt_util
from .state_attributes import decode_attributes_from_source
from .time import process_timestamp
if TYPE_CHECKING:
from functools import cached_property
else:
from homeassistant.backports.functools import cached_property
_LOGGER = logging.getLogger(__name__)
EMPTY_CONTEXT = Context(id=None)
def extract_metadata_ids(
entity_id_to_metadata_id: dict[str, int | None],
@ -36,15 +42,6 @@ def extract_metadata_ids(
class LazyState(State):
"""A lazy version of core State after schema 31."""
__slots__ = [
"_row",
"_attributes",
"_last_changed_ts",
"_last_updated_ts",
"_context",
"attr_cache",
]
def __init__( # pylint: disable=super-init-not-called
self,
row: Row,
@ -61,61 +58,35 @@ class LazyState(State):
self.state = state or ""
self._attributes: dict[str, Any] | None = None
self._last_updated_ts: float | None = last_updated_ts or start_time_ts
self._last_changed_ts: float | None = None
self._context: Context | None = None
self.attr_cache = attr_cache
self.context = EMPTY_CONTEXT
@property # type: ignore[override]
@cached_property # type: ignore[override]
def attributes(self) -> dict[str, Any]:
"""State attributes."""
if self._attributes is None:
self._attributes = decode_attributes_from_source(
return decode_attributes_from_source(
getattr(self._row, "attributes", None), self.attr_cache
)
return self._attributes
@attributes.setter
def attributes(self, value: dict[str, Any]) -> None:
"""Set attributes."""
self._attributes = value
@cached_property
def _last_changed_ts(self) -> float | None:
"""Last changed timestamp."""
return getattr(self._row, "last_changed_ts", None)
@property
def context(self) -> Context:
"""State context."""
if self._context is None:
self._context = Context(id=None)
return self._context
@context.setter
def context(self, value: Context) -> None:
"""Set context."""
self._context = value
@property
def last_changed(self) -> datetime:
@cached_property
def last_changed(self) -> datetime: # type: ignore[override]
"""Last changed datetime."""
if self._last_changed_ts is None:
self._last_changed_ts = (
getattr(self._row, "last_changed_ts", None) or self._last_updated_ts
return dt_util.utc_from_timestamp(
self._last_changed_ts or self._last_updated_ts
)
return dt_util.utc_from_timestamp(self._last_changed_ts)
@last_changed.setter
def last_changed(self, value: datetime) -> None:
"""Set last changed datetime."""
self._last_changed_ts = process_timestamp(value).timestamp()
@property
def last_updated(self) -> datetime:
@cached_property
def last_updated(self) -> datetime: # type: ignore[override]
"""Last updated datetime."""
if TYPE_CHECKING:
assert self._last_updated_ts is not None
return dt_util.utc_from_timestamp(self._last_updated_ts)
@last_updated.setter
def last_updated(self, value: datetime) -> None:
"""Set last updated datetime."""
self._last_updated_ts = process_timestamp(value).timestamp()
def as_dict(self) -> dict[str, Any]: # type: ignore[override]
"""Return a dict representation of the LazyState.

View file

@ -352,22 +352,6 @@ async def test_lazy_state_handles_same_last_updated_and_last_changed(
"last_updated": "2021-06-12T03:04:01.000323+00:00",
"state": "off",
}
lstate.last_updated = datetime(2020, 6, 12, 3, 4, 1, 323, tzinfo=dt_util.UTC)
assert lstate.as_dict() == {
"attributes": {"shared": True},
"entity_id": "sensor.valid",
"last_changed": "2021-06-12T03:04:01.000323+00:00",
"last_updated": "2020-06-12T03:04:01.000323+00:00",
"state": "off",
}
lstate.last_changed = datetime(2020, 6, 12, 3, 4, 1, 323, tzinfo=dt_util.UTC)
assert lstate.as_dict() == {
"attributes": {"shared": True},
"entity_id": "sensor.valid",
"last_changed": "2020-06-12T03:04:01.000323+00:00",
"last_updated": "2020-06-12T03:04:01.000323+00:00",
"state": "off",
}
@pytest.mark.parametrize(