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.
pull/41267/head
J. Nick Koston 2020-10-05 08:08:47 -05:00 committed by GitHub
parent 44580b1c07
commit 20a136e2a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 4 deletions

View File

@ -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)

View File

@ -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,

View File

@ -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