mirror of
https://github.com/home-assistant/core.git
synced 2025-08-08 07:05:07 +02:00
fix slow tests
This commit is contained in:
@@ -82,6 +82,7 @@ from .queries import (
|
||||
find_shared_data_id,
|
||||
get_shared_attributes,
|
||||
get_shared_event_datas,
|
||||
has_event_type_to_migrate,
|
||||
)
|
||||
from .run_history import RunHistory
|
||||
from .table_managers.event_types import EventTypeManager
|
||||
@@ -693,11 +694,26 @@ class Recorder(threading.Thread):
|
||||
_LOGGER.debug("Recorder processing the queue")
|
||||
self._adjust_lru_size()
|
||||
self.hass.add_job(self._async_set_recorder_ready_migration_done)
|
||||
self.queue_task(ContextIDMigrationTask())
|
||||
self.queue_task(EventTypeIDMigrationTask())
|
||||
self._activate_table_managers_or_migrate()
|
||||
self._run_event_loop()
|
||||
self._shutdown()
|
||||
|
||||
def _activate_table_managers_or_migrate(self) -> None:
|
||||
"""Activate the table managers or schedule migrations."""
|
||||
# Currently we always check if context ids need to be migrated
|
||||
# since there are multiple tables. This could be optimized
|
||||
# to check both the states and events table to see if there
|
||||
# are any missing and avoid inserting the task but it currently
|
||||
# is not needed since there is no dependent code branching
|
||||
# on the result of the migration.
|
||||
self.queue_task(ContextIDMigrationTask())
|
||||
with session_scope(session=self.get_session()) as session:
|
||||
if session.execute(has_event_type_to_migrate()).scalar():
|
||||
self.queue_task(EventTypeIDMigrationTask())
|
||||
else:
|
||||
_LOGGER.debug("Activating event type manager as all data is migrated")
|
||||
self.event_type_manager.active = True
|
||||
|
||||
def _run_event_loop(self) -> None:
|
||||
"""Run the event loop for the recorder."""
|
||||
# Use a session for the event read loop
|
||||
|
@@ -577,6 +577,9 @@ def _purge_old_event_types(instance: Recorder, session: Session) -> None:
|
||||
purged_event_types.add(event_type)
|
||||
event_type_ids.add(event_type_id)
|
||||
|
||||
if not event_type_ids:
|
||||
return
|
||||
|
||||
deleted_rows = session.execute(delete_event_types_rows(event_type_ids))
|
||||
_LOGGER.debug("Deleted %s event types", deleted_rows)
|
||||
|
||||
|
@@ -716,6 +716,13 @@ def find_event_type_to_migrate() -> StatementLambdaElement:
|
||||
)
|
||||
|
||||
|
||||
def has_event_type_to_migrate() -> StatementLambdaElement:
|
||||
"""Check if there are event_types to migrate."""
|
||||
return lambda_stmt(
|
||||
lambda: select(Events.event_id).filter(Events.event_type_id.is_(None)).limit(1)
|
||||
)
|
||||
|
||||
|
||||
def find_states_context_ids_to_migrate() -> StatementLambdaElement:
|
||||
"""Find events context_ids to migrate."""
|
||||
return lambda_stmt(
|
||||
|
@@ -21,6 +21,7 @@ from sqlalchemy import (
|
||||
Identity,
|
||||
Index,
|
||||
Integer,
|
||||
LargeBinary,
|
||||
SmallInteger,
|
||||
String,
|
||||
Text,
|
||||
@@ -54,6 +55,7 @@ DB_TIMEZONE = "+00:00"
|
||||
|
||||
TABLE_EVENTS = "events"
|
||||
TABLE_EVENT_DATA = "event_data"
|
||||
TABLE_EVENT_TYPES = "event_types"
|
||||
TABLE_STATES = "states"
|
||||
TABLE_STATE_ATTRIBUTES = "state_attributes"
|
||||
TABLE_RECORDER_RUNS = "recorder_runs"
|
||||
@@ -68,6 +70,7 @@ ALL_TABLES = [
|
||||
TABLE_STATE_ATTRIBUTES,
|
||||
TABLE_EVENTS,
|
||||
TABLE_EVENT_DATA,
|
||||
TABLE_EVENT_TYPES,
|
||||
TABLE_RECORDER_RUNS,
|
||||
TABLE_SCHEMA_CHANGES,
|
||||
TABLE_STATISTICS,
|
||||
@@ -98,6 +101,11 @@ DOUBLE_TYPE = (
|
||||
)
|
||||
EVENT_ORIGIN_ORDER = [EventOrigin.local, EventOrigin.remote]
|
||||
EVENT_ORIGIN_TO_IDX = {origin: idx for idx, origin in enumerate(EVENT_ORIGIN_ORDER)}
|
||||
CONTEXT_ID_BIN_MAX_LENGTH = 16
|
||||
EVENTS_CONTEXT_ID_BIN_INDEX = "ix_events_context_id_bin"
|
||||
STATES_CONTEXT_ID_BIN_INDEX = "ix_states_context_id_bin"
|
||||
|
||||
TIMESTAMP_TYPE = DOUBLE_TYPE
|
||||
|
||||
|
||||
class Events(Base): # type: ignore[misc,valid-type]
|
||||
@@ -107,6 +115,12 @@ class Events(Base): # type: ignore[misc,valid-type]
|
||||
# Used for fetching events at a specific time
|
||||
# see logbook
|
||||
Index("ix_events_event_type_time_fired", "event_type", "time_fired"),
|
||||
Index(
|
||||
EVENTS_CONTEXT_ID_BIN_INDEX,
|
||||
"context_id_bin",
|
||||
mysql_length=CONTEXT_ID_BIN_MAX_LENGTH,
|
||||
mariadb_length=CONTEXT_ID_BIN_MAX_LENGTH,
|
||||
),
|
||||
{"mysql_default_charset": "utf8mb4", "mysql_collate": "utf8mb4_unicode_ci"},
|
||||
)
|
||||
__tablename__ = TABLE_EVENTS
|
||||
@@ -116,11 +130,27 @@ class Events(Base): # type: ignore[misc,valid-type]
|
||||
origin = Column(String(MAX_LENGTH_EVENT_ORIGIN)) # no longer used
|
||||
origin_idx = Column(SmallInteger)
|
||||
time_fired = Column(DATETIME_TYPE, index=True)
|
||||
time_fired_ts = Column(
|
||||
TIMESTAMP_TYPE, index=True
|
||||
) # *** Not originally in v30, only added for recorder to startup ok
|
||||
context_id = Column(String(MAX_LENGTH_EVENT_CONTEXT_ID), index=True)
|
||||
context_user_id = Column(String(MAX_LENGTH_EVENT_CONTEXT_ID))
|
||||
context_parent_id = Column(String(MAX_LENGTH_EVENT_CONTEXT_ID))
|
||||
data_id = Column(Integer, ForeignKey("event_data.data_id"), index=True)
|
||||
context_id_bin = Column(
|
||||
LargeBinary(CONTEXT_ID_BIN_MAX_LENGTH)
|
||||
) # *** Not originally in v28, only added for recorder to startup ok
|
||||
context_user_id_bin = Column(
|
||||
LargeBinary(CONTEXT_ID_BIN_MAX_LENGTH)
|
||||
) # *** Not originally in v28, only added for recorder to startup ok
|
||||
context_parent_id_bin = Column(
|
||||
LargeBinary(CONTEXT_ID_BIN_MAX_LENGTH)
|
||||
) # *** Not originally in v28, only added for recorder to startup ok
|
||||
event_type_id = Column(
|
||||
Integer, ForeignKey("event_types.event_type_id"), index=True
|
||||
) # *** Not originally in v28, only added for recorder to startup ok
|
||||
event_data_rel = relationship("EventData")
|
||||
event_type_rel = relationship("EventTypes")
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""Return string representation of instance for debugging."""
|
||||
@@ -214,6 +244,19 @@ class EventData(Base): # type: ignore[misc,valid-type]
|
||||
return {}
|
||||
|
||||
|
||||
# *** Not originally in v28, only added for recorder to startup ok
|
||||
# This is not being tested by the v28 statistics migration tests
|
||||
class EventTypes(Base): # type: ignore[misc,valid-type]
|
||||
"""Event type history."""
|
||||
|
||||
__table_args__ = (
|
||||
{"mysql_default_charset": "utf8mb4", "mysql_collate": "utf8mb4_unicode_ci"},
|
||||
)
|
||||
__tablename__ = TABLE_EVENT_TYPES
|
||||
event_type_id = Column(Integer, Identity(), primary_key=True)
|
||||
event_type = Column(String(MAX_LENGTH_EVENT_EVENT_TYPE))
|
||||
|
||||
|
||||
class States(Base): # type: ignore[misc,valid-type]
|
||||
"""State change history."""
|
||||
|
||||
|
@@ -214,6 +214,9 @@ class Events(Base): # type: ignore[misc,valid-type]
|
||||
origin = Column(String(MAX_LENGTH_EVENT_ORIGIN)) # no longer used for new rows
|
||||
origin_idx = Column(SmallInteger)
|
||||
time_fired = Column(DATETIME_TYPE, index=True)
|
||||
time_fired_ts = Column(
|
||||
TIMESTAMP_TYPE, index=True
|
||||
) # *** Not originally in v30, only added for recorder to startup ok
|
||||
context_id = Column(String(MAX_LENGTH_EVENT_CONTEXT_ID), index=True)
|
||||
context_user_id = Column(String(MAX_LENGTH_EVENT_CONTEXT_ID))
|
||||
context_parent_id = Column(String(MAX_LENGTH_EVENT_CONTEXT_ID))
|
||||
|
Reference in New Issue
Block a user