Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Add concept of StatelessContext #3550

Closed
wants to merge 9 commits into from

Conversation

erikjohnston
Copy link
Member

This allows us to lazily load state on the master process as required
(when using workers). The advantage of this is that in the common case
the master doesn't need the full state of the events to persist them.

We keep the concept of an EventContext that has the current_state_ids
and prev_state_ids attributes, to avoid having to rewrite a lot of code.
Instead, we shift the necessary functions to accept StatelessContext.

Supersedes #2999


I don't know whether it would be better to completely remove current_state_ids from StatelessContext or not.

This allows us to lazily load state on the master process as required
(when using workers). The advantage of this is that in the common case
the master doesn't need the full state of the events to persist them.

We keep the concept of an EventContext that has the current_state_ids
and prev_state_ids attributes, to avoid having to rewrite a lot of code.
Instead, we shift the necessary functions to accept StatelessContext.
Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks plausible

prev_group (int): Previously persisted state group. ``None`` for an
outlier.
delta_ids (dict[(str, str), str]): Delta from ``prev_group``.
(type, state_key) -> event_id. ``None`` for an outlier.

prev_state_events (?): XXX: is this ever set to anything other than
the empty list?

current_state_ids (dict[(str, str), str]|None):
The current state map including the current event.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we record the circumstances under which we expect it to be set, and which None? (likewise prev_state_ids)

"""Gets the current state IDs

Returns:
Deferred[dict[(str, str), str]|None]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we expect it to return None, ever?

@@ -130,24 +190,56 @@ def deserialize(store, input):

# We use the state_group and prev_state_id stuff to pull the
# current_state_ids out of the DB and construct prev_state_ids.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment seems a bit out-of-place now

"""Called to populate the current_state_ids and prev_state_ids
attributes by loading from the database.
"""
self._have_fetched_state = True
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks racy: what if two threads call get_current_state_ids at once?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[I suggest you store a deferred while the fetch is taking place]

self.current_state_ids = yield store.get_state_ids_for_group(
self.state_group,
)
if self._prev_state_id:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be conditional on event_state_key being not-None?

from frozendict import frozendict

from twisted.internet import defer


class EventContext(object):
class StatelessContext(object):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this feels like a funny name, given it may have a state.

Indeed I wonder if having it separate from EventContext is worthwhile? maybe combine them and have DeserializedContext just override the accessors?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately we can't just override accessors since they would need to return a deferreds in the DeserializedContext

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, but that's also true for EventContext. I don't understand why that means we can't override the accessors.

context.prev_state_ids[(event_type, event_state_key)] = prev_state_id
else:
context.prev_state_ids = context.current_state_ids
context._have_fetched_state = None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this is going to be a Deferred, then it needs a different name.

"""Implements StatelessContext"""

if not self._have_fetched_state:
self._have_fetched_state = self._fill_out_state(store)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need a run_in_background here (and in get_prev_state_ids)

@richvdh richvdh assigned erikjohnston and unassigned richvdh Jul 20, 2018
Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm except for #3550 (comment) which I still don't understan

@erikjohnston erikjohnston deleted the erikj/stateless_contexts_3 branch September 20, 2018 13:57
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants