From 20a136e2a1e805ac7eac665ad16b385e6a9affdb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 5 Oct 2020 08:08:47 -0500 Subject: [PATCH] Avoid event data serialization during recorder that we throw away (#41217) We currently serialize the event data for state change events and then replace it because we save the state in the states table. Since the old state and new state are both contains in the event the cost of serializing the data has a noticable impact when there are many state changed events. --- homeassistant/components/recorder/__init__.py | 5 +++-- homeassistant/components/recorder/models.py | 4 ++-- tests/components/recorder/test_models.py | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/recorder/__init__.py b/homeassistant/components/recorder/__init__.py index 02a07bab628..5ecfad5d204 100644 --- a/homeassistant/components/recorder/__init__.py +++ b/homeassistant/components/recorder/__init__.py @@ -381,9 +381,10 @@ class Recorder(threading.Thread): continue try: - dbevent = Events.from_event(event) if event.event_type == EVENT_STATE_CHANGED: - dbevent.event_data = "{}" + dbevent = Events.from_event(event, event_data="{}") + else: + dbevent = Events.from_event(event) self.event_session.add(dbevent) except (TypeError, ValueError): _LOGGER.warning("Event is not JSON serializable: %s", event) diff --git a/homeassistant/components/recorder/models.py b/homeassistant/components/recorder/models.py index 642407cf0c6..e0f733fbfa0 100644 --- a/homeassistant/components/recorder/models.py +++ b/homeassistant/components/recorder/models.py @@ -60,11 +60,11 @@ class Events(Base): # type: ignore ) @staticmethod - def from_event(event): + def from_event(event, event_data=None): """Create an event database object from a native event.""" return Events( event_type=event.event_type, - event_data=json.dumps(event.data, cls=JSONEncoder), + event_data=event_data or json.dumps(event.data, cls=JSONEncoder), origin=str(event.origin), time_fired=event.time_fired, context_id=event.context.id, diff --git a/tests/components/recorder/test_models.py b/tests/components/recorder/test_models.py index bf659282e3e..c11fa8a692f 100644 --- a/tests/components/recorder/test_models.py +++ b/tests/components/recorder/test_models.py @@ -19,6 +19,7 @@ from homeassistant.const import EVENT_STATE_CHANGED import homeassistant.core as ha from homeassistant.exceptions import InvalidEntityFormatError from homeassistant.util import dt +import homeassistant.util.dt as dt_util ENGINE = None SESSION = None @@ -241,3 +242,16 @@ async def test_process_timestamp_to_utc_isoformat(): == "2016-07-09T21:31:00+00:00" ) assert process_timestamp_to_utc_isoformat(None) is None + + +async def test_event_to_db_model(): + """Test we can round trip Event conversion.""" + event = ha.Event( + "state_changed", {"some": "attr"}, ha.EventOrigin.local, dt_util.utcnow() + ) + native = Events.from_event(event).to_native() + assert native == event + + native = Events.from_event(event, event_data="{}").to_native() + event.data = {} + assert native == event