mirror of
https://github.com/element-hq/synapse.git
synced 2025-12-05 01:10:13 +00:00
Compare commits
4 Commits
erikj/dock
...
erikj/even
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bf4d5e465 | ||
|
|
ea7735b6f3 | ||
|
|
aa11e60fc7 | ||
|
|
75ca54cd52 |
@@ -13,8 +13,11 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from synapse.util.frozenutils import freeze
|
||||
from synapse.util.caches import intern_dict
|
||||
from synapse.util.frozenutils import freeze, unfreeze
|
||||
from synapse.util.caches import intern_dict, intern_string
|
||||
|
||||
import abc
|
||||
import simplejson as json
|
||||
|
||||
|
||||
# Whether we should use frozen_dict in FrozenEvent. Using frozen_dicts prevents
|
||||
@@ -64,30 +67,46 @@ def _event_dict_property(key):
|
||||
|
||||
|
||||
class EventBase(object):
|
||||
def __init__(self, event_dict, signatures={}, unsigned={},
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
||||
def __init__(self, signatures={}, unsigned={},
|
||||
internal_metadata_dict={}, rejected_reason=None):
|
||||
self.signatures = signatures
|
||||
self.unsigned = unsigned
|
||||
self.rejected_reason = rejected_reason
|
||||
|
||||
self._event_dict = event_dict
|
||||
|
||||
self.internal_metadata = _EventInternalMetadata(
|
||||
internal_metadata_dict
|
||||
)
|
||||
|
||||
auth_events = _event_dict_property("auth_events")
|
||||
depth = _event_dict_property("depth")
|
||||
content = _event_dict_property("content")
|
||||
hashes = _event_dict_property("hashes")
|
||||
origin = _event_dict_property("origin")
|
||||
origin_server_ts = _event_dict_property("origin_server_ts")
|
||||
prev_events = _event_dict_property("prev_events")
|
||||
prev_state = _event_dict_property("prev_state")
|
||||
redacts = _event_dict_property("redacts")
|
||||
room_id = _event_dict_property("room_id")
|
||||
sender = _event_dict_property("sender")
|
||||
user_id = _event_dict_property("sender")
|
||||
auth_events = abc.abstractproperty()
|
||||
depth = abc.abstractproperty()
|
||||
content = abc.abstractproperty()
|
||||
hashes = abc.abstractproperty()
|
||||
origin = abc.abstractproperty()
|
||||
origin_server_ts = abc.abstractproperty()
|
||||
prev_events = abc.abstractproperty()
|
||||
prev_state = abc.abstractproperty()
|
||||
redacts = abc.abstractproperty()
|
||||
room_id = abc.abstractproperty()
|
||||
sender = abc.abstractproperty()
|
||||
user_id = abc.abstractproperty()
|
||||
|
||||
event_id = abc.abstractproperty()
|
||||
state_key = abc.abstractproperty()
|
||||
type = abc.abstractproperty()
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_dict(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
@abc.abstractmethod
|
||||
def get(self, key, default=None):
|
||||
raise NotImplementedError()
|
||||
|
||||
@abc.abstractmethod
|
||||
def iteritems(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
@property
|
||||
def membership(self):
|
||||
@@ -96,18 +115,6 @@ class EventBase(object):
|
||||
def is_state(self):
|
||||
return hasattr(self, "state_key") and self.state_key is not None
|
||||
|
||||
def get_dict(self):
|
||||
d = dict(self._event_dict)
|
||||
d.update({
|
||||
"signatures": self.signatures,
|
||||
"unsigned": dict(self.unsigned),
|
||||
})
|
||||
|
||||
return d
|
||||
|
||||
def get(self, key, default=None):
|
||||
return self._event_dict.get(key, default)
|
||||
|
||||
def get_internal_metadata_dict(self):
|
||||
return self.internal_metadata.get_dict()
|
||||
|
||||
@@ -127,15 +134,6 @@ class EventBase(object):
|
||||
def __set__(self, instance, value):
|
||||
raise AttributeError("Unrecognized attribute %s" % (instance,))
|
||||
|
||||
def __getitem__(self, field):
|
||||
return self._event_dict[field]
|
||||
|
||||
def __contains__(self, field):
|
||||
return field in self._event_dict
|
||||
|
||||
def items(self):
|
||||
return self._event_dict.items()
|
||||
|
||||
|
||||
class FrozenEvent(EventBase):
|
||||
def __init__(self, event_dict, internal_metadata_dict={}, rejected_reason=None):
|
||||
@@ -159,19 +157,60 @@ class FrozenEvent(EventBase):
|
||||
else:
|
||||
frozen_dict = event_dict
|
||||
|
||||
self.event_id = event_dict["event_id"]
|
||||
self.type = event_dict["type"]
|
||||
self._event_id = event_dict["event_id"]
|
||||
self._type = event_dict["type"]
|
||||
if "state_key" in event_dict:
|
||||
self.state_key = event_dict["state_key"]
|
||||
self._state_key = event_dict["state_key"]
|
||||
|
||||
self._event_dict = frozen_dict
|
||||
|
||||
super(FrozenEvent, self).__init__(
|
||||
frozen_dict,
|
||||
signatures=signatures,
|
||||
unsigned=unsigned,
|
||||
internal_metadata_dict=internal_metadata_dict,
|
||||
rejected_reason=rejected_reason,
|
||||
)
|
||||
|
||||
auth_events = _event_dict_property("auth_events")
|
||||
depth = _event_dict_property("depth")
|
||||
content = _event_dict_property("content")
|
||||
hashes = _event_dict_property("hashes")
|
||||
origin = _event_dict_property("origin")
|
||||
origin_server_ts = _event_dict_property("origin_server_ts")
|
||||
prev_events = _event_dict_property("prev_events")
|
||||
prev_state = _event_dict_property("prev_state")
|
||||
redacts = _event_dict_property("redacts")
|
||||
room_id = _event_dict_property("room_id")
|
||||
sender = _event_dict_property("sender")
|
||||
user_id = _event_dict_property("sender")
|
||||
|
||||
@property
|
||||
def event_id(self):
|
||||
return self._event_id
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self._type
|
||||
|
||||
@property
|
||||
def state_key(self):
|
||||
return self._state_key
|
||||
|
||||
def get_dict(self):
|
||||
d = dict(self._event_dict)
|
||||
d.update({
|
||||
"signatures": self.signatures,
|
||||
"unsigned": dict(self.unsigned),
|
||||
})
|
||||
|
||||
return d
|
||||
|
||||
def get(self, key, default=None):
|
||||
return self._event_dict.get(key, default)
|
||||
|
||||
def iteritems(self):
|
||||
return self._event_dict.iteritems()
|
||||
|
||||
@staticmethod
|
||||
def from_event(event):
|
||||
e = FrozenEvent(
|
||||
@@ -191,3 +230,200 @@ class FrozenEvent(EventBase):
|
||||
self.get("type", None),
|
||||
self.get("state_key", None),
|
||||
)
|
||||
|
||||
|
||||
def _compact_property(key):
|
||||
def getter(self):
|
||||
try:
|
||||
return self[key]
|
||||
except KeyError:
|
||||
raise AttributeError(
|
||||
"AttributeError: '%s' object has no attribute '%s'" % (
|
||||
self.__name__, key,
|
||||
)
|
||||
)
|
||||
|
||||
return property(getter)
|
||||
|
||||
|
||||
class _Unsigned(object):
|
||||
__slots__ = [
|
||||
"age_ts",
|
||||
"replaces_state",
|
||||
"redacted_because",
|
||||
"invite_room_state",
|
||||
"prev_content",
|
||||
"prev_sender",
|
||||
"redacted_by",
|
||||
]
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
for s in self.__slots__:
|
||||
try:
|
||||
setattr(self, s, kwargs[s])
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
def __getitem__(self, field):
|
||||
try:
|
||||
return getattr(self, field)
|
||||
except AttributeError:
|
||||
raise KeyError(field)
|
||||
|
||||
def __setitem__(self, field, value):
|
||||
try:
|
||||
setattr(self, field, value)
|
||||
except AttributeError:
|
||||
raise KeyError(field)
|
||||
|
||||
def __delitem__(self, field):
|
||||
try:
|
||||
return delattr(self, field)
|
||||
except AttributeError:
|
||||
raise KeyError(field)
|
||||
|
||||
def __contains__(self, field):
|
||||
return hasattr(self, field)
|
||||
|
||||
def get(self, key, default=None):
|
||||
return getattr(self, key, default)
|
||||
|
||||
def pop(self, key, default):
|
||||
r = self.get(key, default)
|
||||
try:
|
||||
delattr(self, key)
|
||||
except AttributeError:
|
||||
pass
|
||||
return r
|
||||
|
||||
def __iter__(self):
|
||||
for key in self.__slots__:
|
||||
if hasattr(self, key):
|
||||
yield (key, getattr(self, key))
|
||||
|
||||
|
||||
class CompactEvent(EventBase):
|
||||
__slots__ = [
|
||||
"event_json",
|
||||
|
||||
"internal_metadata",
|
||||
"rejected_reason",
|
||||
|
||||
"signatures",
|
||||
"unsigned",
|
||||
|
||||
"event_id",
|
||||
"room_id",
|
||||
"type",
|
||||
"state_key",
|
||||
"sender",
|
||||
]
|
||||
|
||||
def __init__(self, event_dict, internal_metadata_dict={}, rejected_reason=None):
|
||||
event_dict = dict(unfreeze(event_dict))
|
||||
|
||||
object.__setattr__(self, "unsigned", _Unsigned(**event_dict.pop("unsigned", {})))
|
||||
|
||||
signatures = {
|
||||
intern_string(name): {
|
||||
intern_string(sig_id): sig.encode("utf-8")
|
||||
for sig_id, sig in sigs.iteritems()
|
||||
}
|
||||
for name, sigs in event_dict.pop("signatures", {}).iteritems()
|
||||
}
|
||||
object.__setattr__(self, "signatures", signatures)
|
||||
|
||||
object.__setattr__(self, "event_json", json.dumps(event_dict))
|
||||
|
||||
object.__setattr__(self, "rejected_reason", rejected_reason)
|
||||
object.__setattr__(self, "internal_metadata", _EventInternalMetadata(
|
||||
internal_metadata_dict
|
||||
))
|
||||
|
||||
object.__setattr__(self, "event_id", event_dict["event_id"])
|
||||
object.__setattr__(self, "room_id", event_dict["room_id"])
|
||||
object.__setattr__(self, "type", event_dict["type"])
|
||||
if "state_key" in event_dict:
|
||||
object.__setattr__(self, "state_key", event_dict["state_key"])
|
||||
object.__setattr__(self, "sender", event_dict["sender"])
|
||||
|
||||
auth_events = _compact_property("auth_events")
|
||||
depth = _compact_property("depth")
|
||||
content = _compact_property("content")
|
||||
hashes = _compact_property("hashes")
|
||||
origin = _compact_property("origin")
|
||||
origin_server_ts = _compact_property("origin_server_ts")
|
||||
prev_events = _compact_property("prev_events")
|
||||
prev_state = _compact_property("prev_state")
|
||||
redacts = _compact_property("redacts")
|
||||
|
||||
@property
|
||||
def user_id(self):
|
||||
return self.sender
|
||||
|
||||
@property
|
||||
def membership(self):
|
||||
return self.content["membership"]
|
||||
|
||||
def is_state(self):
|
||||
return hasattr(self, "state_key") and self.state_key is not None
|
||||
|
||||
def get_dict(self):
|
||||
d = json.loads(self.event_json)
|
||||
d.update({
|
||||
"signatures": dict(self.signatures),
|
||||
"unsigned": dict(self.unsigned),
|
||||
})
|
||||
|
||||
return d
|
||||
|
||||
def get(self, key, default=None):
|
||||
if key in self.__slots__:
|
||||
return freeze(getattr(self, key, default))
|
||||
|
||||
d = json.loads(self.event_json)
|
||||
return d.get(key, default)
|
||||
|
||||
def get_internal_metadata_dict(self):
|
||||
return self.internal_metadata.get_dict()
|
||||
|
||||
def __getitem__(self, field):
|
||||
if field in self.__slots__:
|
||||
try:
|
||||
return freeze(getattr(self, field))
|
||||
except AttributeError:
|
||||
raise KeyError(field)
|
||||
|
||||
d = json.loads(self.event_json)
|
||||
return d[field]
|
||||
|
||||
def __contains__(self, field):
|
||||
if field in self.__slots__:
|
||||
return hasattr(self, field)
|
||||
|
||||
d = json.loads(self.event_json)
|
||||
return field in d
|
||||
|
||||
@staticmethod
|
||||
def from_event(event):
|
||||
return CompactEvent(
|
||||
event.get_pdu_json(),
|
||||
event.get_internal_metadata_dict(),
|
||||
event.rejected_reason,
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.__repr__()
|
||||
|
||||
def __repr__(self):
|
||||
return "<CompactEvent event_id='%s', type='%s', state_key='%s'>" % (
|
||||
self.get("event_id", None),
|
||||
self.get("type", None),
|
||||
self.get("state_key", None),
|
||||
)
|
||||
|
||||
def iteritems(self):
|
||||
return json.loads(self.event_json).iteritems()
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.event_id == other.event_id
|
||||
|
||||
@@ -27,8 +27,9 @@ class EventBuilder(EventBase):
|
||||
signatures = copy.deepcopy(key_values.pop("signatures", {}))
|
||||
unsigned = copy.deepcopy(key_values.pop("unsigned", {}))
|
||||
|
||||
self._event_dict = key_values
|
||||
|
||||
super(EventBuilder, self).__init__(
|
||||
key_values,
|
||||
signatures=signatures,
|
||||
unsigned=unsigned,
|
||||
internal_metadata_dict=internal_metadata_dict,
|
||||
@@ -38,6 +39,34 @@ class EventBuilder(EventBase):
|
||||
state_key = _event_dict_property("state_key")
|
||||
type = _event_dict_property("type")
|
||||
|
||||
auth_events = _event_dict_property("auth_events")
|
||||
depth = _event_dict_property("depth")
|
||||
content = _event_dict_property("content")
|
||||
hashes = _event_dict_property("hashes")
|
||||
origin = _event_dict_property("origin")
|
||||
origin_server_ts = _event_dict_property("origin_server_ts")
|
||||
prev_events = _event_dict_property("prev_events")
|
||||
prev_state = _event_dict_property("prev_state")
|
||||
redacts = _event_dict_property("redacts")
|
||||
room_id = _event_dict_property("room_id")
|
||||
sender = _event_dict_property("sender")
|
||||
user_id = _event_dict_property("sender")
|
||||
|
||||
def get_dict(self):
|
||||
d = dict(self._event_dict)
|
||||
d.update({
|
||||
"signatures": self.signatures,
|
||||
"unsigned": dict(self.unsigned),
|
||||
})
|
||||
|
||||
return d
|
||||
|
||||
def get(self, key, default=None):
|
||||
return self._event_dict.get(key, default)
|
||||
|
||||
def iteritems(self):
|
||||
return self._event_dict.iteritems()
|
||||
|
||||
def build(self):
|
||||
return FrozenEvent.from_event(self)
|
||||
|
||||
|
||||
@@ -261,6 +261,8 @@ class MessageHandler(BaseHandler):
|
||||
|
||||
time_now = self.clock.time_msec()
|
||||
|
||||
logger.info("Returning event: %r", events)
|
||||
|
||||
chunk = {
|
||||
"chunk": [
|
||||
serialize_event(e, time_now, as_client_event)
|
||||
@@ -624,6 +626,7 @@ class EventCreationHandler(object):
|
||||
context.app_service = requester.app_service
|
||||
|
||||
if builder.is_state():
|
||||
logger.info("Added prev_state")
|
||||
builder.prev_state = yield self.store.add_event_hashes(
|
||||
context.prev_state_events
|
||||
)
|
||||
|
||||
@@ -313,7 +313,7 @@ class HttpPusher(object):
|
||||
if event.type == 'm.room.member':
|
||||
d['notification']['membership'] = event.content['membership']
|
||||
d['notification']['user_is_target'] = event.state_key == self.user_id
|
||||
if self.hs.config.push_include_content and 'content' in event:
|
||||
if self.hs.config.push_include_content:
|
||||
d['notification']['content'] = event.content
|
||||
|
||||
# We no longer send aliases separately, instead, we send the human
|
||||
|
||||
@@ -122,7 +122,7 @@ class PushRuleEvaluatorForEvent(object):
|
||||
|
||||
# XXX: optimisation: cache our pattern regexps
|
||||
if condition['key'] == 'content.body':
|
||||
body = self._event["content"].get("body", None)
|
||||
body = self._event.content.get("body", None)
|
||||
if not body:
|
||||
return False
|
||||
|
||||
@@ -138,7 +138,7 @@ class PushRuleEvaluatorForEvent(object):
|
||||
if not display_name:
|
||||
return False
|
||||
|
||||
body = self._event["content"].get("body", None)
|
||||
body = self._event.content.get("body", None)
|
||||
if not body:
|
||||
return False
|
||||
|
||||
@@ -237,10 +237,10 @@ def _re_word_boundary(r):
|
||||
def _flatten_dict(d, prefix=[], result=None):
|
||||
if result is None:
|
||||
result = {}
|
||||
for key, value in d.items():
|
||||
for key, value in d.iteritems():
|
||||
if isinstance(value, basestring):
|
||||
result[".".join(prefix + [key])] = value.lower()
|
||||
elif hasattr(value, "items"):
|
||||
elif hasattr(value, "iteritems"):
|
||||
_flatten_dict(value, prefix=(prefix + [key]), result=result)
|
||||
|
||||
return result
|
||||
|
||||
@@ -18,7 +18,7 @@ from synapse.storage.events_worker import EventsWorkerStore
|
||||
|
||||
from twisted.internet import defer
|
||||
|
||||
from synapse.events import USE_FROZEN_DICTS
|
||||
from synapse.events import USE_FROZEN_DICTS, CompactEvent
|
||||
|
||||
from synapse.util.async import ObservableDeferred
|
||||
from synapse.util.logcontext import (
|
||||
@@ -1254,7 +1254,7 @@ class EventsStore(EventsWorkerStore):
|
||||
event = ev_map[row["event_id"]]
|
||||
if not row["rejects"] and not row["redacts"]:
|
||||
to_prefill.append(_EventCacheEntry(
|
||||
event=event,
|
||||
event=CompactEvent.from_event(event),
|
||||
redacted_event=None,
|
||||
))
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ from ._base import SQLBaseStore
|
||||
|
||||
from twisted.internet import defer, reactor
|
||||
|
||||
from synapse.events import FrozenEvent
|
||||
from synapse.events import CompactEvent
|
||||
from synapse.events.utils import prune_event
|
||||
|
||||
from synapse.util.logcontext import (
|
||||
@@ -69,7 +69,7 @@ class EventsWorkerStore(SQLBaseStore):
|
||||
False throw an exception.
|
||||
|
||||
Returns:
|
||||
Deferred : A FrozenEvent.
|
||||
Deferred : A CompactEvent.
|
||||
"""
|
||||
events = yield self._get_events(
|
||||
[event_id],
|
||||
@@ -354,7 +354,7 @@ class EventsWorkerStore(SQLBaseStore):
|
||||
desc="_get_event_from_row_rejected_reason",
|
||||
)
|
||||
|
||||
original_ev = FrozenEvent(
|
||||
original_ev = CompactEvent(
|
||||
d,
|
||||
internal_metadata_dict=internal_metadata,
|
||||
rejected_reason=rejected_reason,
|
||||
|
||||
Reference in New Issue
Block a user