Reduce recorder overhead when entity filter is empty (#119631)

pull/119673/head
J. Nick Koston 2024-06-14 01:43:51 -05:00 committed by GitHub
parent 9f41133bbc
commit 9082dc2a79
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 19 additions and 12 deletions

View File

@ -127,15 +127,15 @@ def is_entity_recorded(hass: HomeAssistant, entity_id: str) -> bool:
Async friendly.
"""
if DATA_INSTANCE not in hass.data:
return False
return hass.data[DATA_INSTANCE].entity_filter(entity_id)
instance = get_instance(hass)
return instance.entity_filter is None or instance.entity_filter(entity_id)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the recorder."""
conf = config[DOMAIN]
entity_filter = convert_include_exclude_filter(conf).get_filter()
_filter = convert_include_exclude_filter(conf)
entity_filter = None if _filter.empty_filter else _filter.get_filter()
auto_purge = conf[CONF_AUTO_PURGE]
auto_repack = conf[CONF_AUTO_REPACK]
keep_days = conf[CONF_PURGE_KEEP_DAYS]

View File

@ -178,7 +178,7 @@ class Recorder(threading.Thread):
uri: str,
db_max_retries: int,
db_retry_wait: int,
entity_filter: Callable[[str], bool],
entity_filter: Callable[[str], bool] | None,
exclude_event_types: set[EventType[Any] | str],
) -> None:
"""Initialize the recorder."""
@ -318,7 +318,10 @@ class Recorder(threading.Thread):
if event.event_type in exclude_event_types:
return
if (entity_id := event.data.get(ATTR_ENTITY_ID)) is None:
if (
entity_filter is None
or (entity_id := event.data.get(ATTR_ENTITY_ID)) is None
):
queue_put(event)
return

View File

@ -645,7 +645,7 @@ def _purge_filtered_data(instance: Recorder, session: Session) -> bool:
for (metadata_id, entity_id) in session.query(
StatesMeta.metadata_id, StatesMeta.entity_id
).all()
if not entity_filter(entity_id)
if entity_filter and not entity_filter(entity_id)
]
if excluded_metadata_ids:
has_more_states_to_purge = _purge_filtered_states(
@ -765,7 +765,9 @@ def _purge_filtered_events(
@retryable_database_job("purge_entity_data")
def purge_entity_data(
instance: Recorder, entity_filter: Callable[[str], bool], purge_before: datetime
instance: Recorder,
entity_filter: Callable[[str], bool] | None,
purge_before: datetime,
) -> bool:
"""Purge states and events of specified entities."""
database_engine = instance.database_engine
@ -777,7 +779,7 @@ def purge_entity_data(
for (metadata_id, entity_id) in session.query(
StatesMeta.metadata_id, StatesMeta.entity_id
).all()
if entity_filter(entity_id)
if entity_filter and entity_filter(entity_id)
]
_LOGGER.debug("Purging entity data for %s", selected_metadata_ids)
if not selected_metadata_ids:

View File

@ -80,6 +80,7 @@ def _get_sensor_states(hass: HomeAssistant) -> list[State]:
# We check for state class first before calling the filter
# function as the filter function is much more expensive
# than checking the state class
entity_filter = instance.entity_filter
return [
state
for state in hass.states.all(DOMAIN)
@ -88,7 +89,7 @@ def _get_sensor_states(hass: HomeAssistant) -> list[State]:
type(state_class) is SensorStateClass
or try_parse_enum(SensorStateClass, state_class)
)
and instance.entity_filter(state.entity_id)
and (not entity_filter or entity_filter(state.entity_id))
]
@ -680,6 +681,7 @@ def validate_statistics(
sensor_entity_ids = {i.entity_id for i in sensor_states}
sensor_statistic_ids = set(metadatas)
instance = get_instance(hass)
entity_filter = instance.entity_filter
for state in sensor_states:
entity_id = state.entity_id
@ -689,7 +691,7 @@ def validate_statistics(
state_unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
if metadata := metadatas.get(entity_id):
if not instance.entity_filter(state.entity_id):
if entity_filter and not entity_filter(state.entity_id):
# Sensor was previously recorded, but no longer is
validation_result[entity_id].append(
statistics.ValidationIssue(
@ -739,7 +741,7 @@ def validate_statistics(
)
)
elif state_class is not None:
if not instance.entity_filter(state.entity_id):
if entity_filter and not entity_filter(state.entity_id):
# Sensor is not recorded
validation_result[entity_id].append(
statistics.ValidationIssue(