Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 8 additions & 4 deletions homeassistant/components/recorder/history.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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)
Expand All @@ -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}
Expand Down
11 changes: 10 additions & 1 deletion homeassistant/components/recorder/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -544,12 +545,18 @@ def __init__(self, row): # pylint: disable=super-init-not-called
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
Expand All @@ -561,6 +568,8 @@ def attributes(self):
"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
Expand Down