Cache parsing attr in LazyState (#68232)

This commit is contained in:
J. Nick Koston 2022-03-18 04:44:37 -10:00 committed by GitHub
parent 41a032e3e3
commit 9864090e0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 5 deletions

View File

@ -321,7 +321,9 @@ def _get_states_with_session(
query = query.outerjoin(
StateAttributes, (States.attributes_id == StateAttributes.attributes_id)
)
return [LazyState(row) for row in execute(query)]
attr_cache = {}
return [LazyState(row, attr_cache) for row in execute(query)]
def _get_single_entity_states_with_session(hass, session, utc_point_in_time, entity_id):
@ -397,15 +399,17 @@ def _sorted_states_to_dict(
for ent_id, group in groupby(states, lambda state: state.entity_id):
domain = split_entity_id(ent_id)[0]
ent_results = result[ent_id]
attr_cache = {}
if not minimal_response or domain in NEED_ATTRIBUTE_DOMAINS:
ent_results.extend(LazyState(db_state) for db_state in group)
ent_results.extend(LazyState(db_state, attr_cache) for db_state in group)
# With minimal response we only provide a native
# State for the first and last response. All the states
# in-between only provide the "state" and the
# "last_changed".
if not ent_results:
ent_results.append(LazyState(next(group)))
ent_results.append(LazyState(next(group), attr_cache))
prev_state = ent_results[-1]
initial_state_count = len(ent_results)
@ -430,7 +434,7 @@ def _sorted_states_to_dict(
# There was at least one state change
# replace the last minimal state with
# a full state
ent_results[-1] = LazyState(prev_state)
ent_results[-1] = LazyState(prev_state, attr_cache)
# Filter out the empty lists if some states had 0 results.
return {key: val for key, val in result.items() if val}

View File

@ -533,9 +533,10 @@ class LazyState(State):
"_last_changed",
"_last_updated",
"_context",
"_attr_cache",
]
def __init__(self, row): # pylint: disable=super-init-not-called
def __init__(self, row, attr_cache=None): # pylint: disable=super-init-not-called
"""Init the lazy state."""
self._row = row
self.entity_id = self._row.entity_id
@ -544,12 +545,18 @@ class LazyState(State):
self._last_changed = None
self._last_updated = None
self._context = None
self._attr_cache = attr_cache
@property # type: ignore[override]
def attributes(self):
"""State attributes."""
if self._attributes is None:
source = self._row.shared_attrs or self._row.attributes
if self._attr_cache is not None and (
attributes := self._attr_cache.get(source)
):
self._attributes = attributes
return attributes
if source == EMPTY_JSON_OBJECT or source is None:
self._attributes = {}
return self._attributes
@ -561,6 +568,8 @@ class LazyState(State):
"Error converting row to state attributes: %s", self._row
)
self._attributes = {}
if self._attr_cache is not None:
self._attr_cache[source] = self._attributes
return self._attributes
@attributes.setter