def wait_for_events(self, user, rooms, filter, timeout, callback): """Wait until the callback returns a non empty response or the timeout fires. """ deferred = defer.Deferred() from_token = StreamToken("s0", "0", "0") listener = [ _NotificationListener( user=user, rooms=rooms, from_token=from_token, limit=1, timeout=timeout, deferred=deferred, ) ] if timeout: self._register_with_keys(listener[0]) result = yield callback() timer = [None] if timeout: timed_out = [False] def _timeout_listener(): timed_out[0] = True timer[0] = None listener[0].notify(self, [], from_token, from_token) # We create multiple notification listeners so we have to manage # canceling the timeout ourselves. timer[0] = self.clock.call_later(timeout / 1000., _timeout_listener) while not result and not timed_out[0]: yield deferred deferred = defer.Deferred() listener[0] = _NotificationListener( user=user, rooms=rooms, from_token=from_token, limit=1, timeout=timeout, deferred=deferred, ) self._register_with_keys(listener[0]) result = yield callback() if timer[0] is not None: try: self.clock.cancel_call_later(timer[0]) except: logger.exception("Failed to cancel notifer timer") defer.returnValue(result)
def get_current_token(self, direction='f'): token = StreamToken( room_key=(yield self.sources["room"].get_current_key(direction)), presence_key=(yield self.sources["presence"].get_current_key()), typing_key=(yield self.sources["typing"].get_current_key()), receipt_key=(yield self.sources["receipt"].get_current_key()), ) defer.returnValue(token)
def _room_initial_sync_parted(self, user_id, room_id, pagin_config, membership, member_event_id, is_guest): room_state = yield self.store.get_state_for_events( [member_event_id], None ) room_state = room_state[member_event_id] limit = pagin_config.limit if pagin_config else None if limit is None: limit = 10 stream_token = yield self.store.get_stream_token_for_event( member_event_id ) messages, token = yield self.store.get_recent_events_for_room( room_id, limit=limit, end_token=stream_token ) messages = yield self._filter_events_for_client( user_id, messages, is_guest=is_guest ) start_token = StreamToken(token[0], 0, 0, 0, 0) end_token = StreamToken(token[1], 0, 0, 0, 0) time_now = self.clock.time_msec() defer.returnValue({ "membership": membership, "room_id": room_id, "messages": { "chunk": [serialize_event(m, time_now) for m in messages], "start": start_token.to_string(), "end": end_token.to_string(), }, "state": [serialize_event(s, time_now) for s in room_state.values()], "presence": [], "receipts": [], })
def get_current_token(self): token = StreamToken( room_key=( yield self.sources["room"].get_current_key() ), presence_key=( yield self.sources["presence"].get_current_key() ), typing_key=( yield self.sources["typing"].get_current_key() ) ) defer.returnValue(token)
def get_current_token(self, direction='f'): push_rules_key, _ = self.store.get_push_rules_stream_token() token = StreamToken( room_key=(yield self.sources["room"].get_current_key(direction)), presence_key=(yield self.sources["presence"].get_current_key()), typing_key=(yield self.sources["typing"].get_current_key()), receipt_key=(yield self.sources["receipt"].get_current_key()), account_data_key=(yield self.sources["account_data"].get_current_key()), push_rules_key=push_rules_key, ) defer.returnValue(token)
def get_current_token_for_room(self, room_id): push_rules_key, _ = self.store.get_push_rules_stream_token() to_device_key = self.store.get_to_device_stream_token() token = StreamToken( room_key=(yield self.sources["room"].get_current_key_for_room(room_id)), presence_key=(yield self.sources["presence"].get_current_key()), typing_key=(yield self.sources["typing"].get_current_key()), receipt_key=(yield self.sources["receipt"].get_current_key()), account_data_key=(yield self.sources["account_data"].get_current_key()), push_rules_key=push_rules_key, to_device_key=to_device_key, ) defer.returnValue(token)
def wait_for_events(self, user, rooms, filter, timeout, callback): """Wait until the callback returns a non empty response or the timeout fires. """ deferred = defer.Deferred() from_token = StreamToken("s0", "0", "0") listener = [_NotificationListener( user=user, rooms=rooms, from_token=from_token, limit=1, timeout=timeout, deferred=deferred, )] if timeout: self._register_with_keys(listener[0]) result = yield callback() if timeout: timed_out = [False] def _timeout_listener(): timed_out[0] = True listener[0].notify(self, [], from_token, from_token) self.clock.call_later(timeout/1000., _timeout_listener) while not result and not timed_out[0]: yield deferred deferred = defer.Deferred() listener[0] = _NotificationListener( user=user, rooms=rooms, from_token=from_token, limit=1, timeout=timeout, deferred=deferred, ) self._register_with_keys(listener[0]) result = yield callback() defer.returnValue(result)
def get_current_token(self) -> StreamToken: push_rules_key = self.store.get_max_push_rules_stream_id() to_device_key = self.store.get_to_device_stream_token() device_list_key = self.store.get_device_stream_token() groups_key = self.store.get_group_stream_token() token = StreamToken( room_key=self.sources["room"].get_current_key(), presence_key=self.sources["presence"].get_current_key(), typing_key=self.sources["typing"].get_current_key(), receipt_key=self.sources["receipt"].get_current_key(), account_data_key=self.sources["account_data"].get_current_key(), push_rules_key=push_rules_key, to_device_key=to_device_key, device_list_key=device_list_key, groups_key=groups_key, ) return token
def get_current_token(self) -> StreamToken: push_rules_key = self.store.get_max_push_rules_stream_id() to_device_key = self.store.get_to_device_stream_token() device_list_key = self.store.get_device_stream_token() token = StreamToken( room_key=self.sources.room.get_current_key(), presence_key=self.sources.presence.get_current_key(), typing_key=self.sources.typing.get_current_key(), receipt_key=self.sources.receipt.get_current_key(), account_data_key=self.sources.account_data.get_current_key(), push_rules_key=push_rules_key, to_device_key=to_device_key, device_list_key=device_list_key, # Groups key is unused. groups_key=0, ) return token
def get_current_token_for_pagination(self): """Get the current token for a given room to be used to paginate events. The returned token does not have the current values for fields other than `room`, since they are not used during pagination. Returns: Deferred[StreamToken] """ token = StreamToken( room_key=(yield self.sources["room"].get_current_key()), presence_key=0, typing_key=0, receipt_key=0, account_data_key=0, push_rules_key=0, to_device_key=0, device_list_key=0, groups_key=0, ) return token
async def get_current_token_for_pagination(self, room_id: str) -> StreamToken: """Get the current token for a given room to be used to paginate events. The returned token does not have the current values for fields other than `room`, since they are not used during pagination. Returns: The current token for pagination. """ token = StreamToken( room_key=await self.sources.room.get_current_key_for_room(room_id), presence_key=0, typing_key=0, receipt_key=0, account_data_key=0, push_rules_key=0, to_device_key=0, device_list_key=0, groups_key=0, ) return token
def _get_recent_references_for_event_txn( txn: LoggingTransaction, ) -> Tuple[List[_RelatedEvent], Optional[StreamToken]]: txn.execute(sql, where_args + [limit + 1]) last_topo_id = None last_stream_id = None events = [] for row in txn: # Do not include edits for redacted events as they leak event # content. if not is_redacted or row[1] != RelationTypes.REPLACE: events.append(_RelatedEvent(row[0], row[2])) last_topo_id = row[3] last_stream_id = row[4] # If there are more events, generate the next pagination key. next_token = None if len(events) > limit and last_topo_id and last_stream_id: next_key = RoomStreamToken(last_topo_id, last_stream_id) if from_token: next_token = from_token.copy_and_replace( StreamKeyType.ROOM, next_key) else: next_token = StreamToken( room_key=next_key, presence_key=0, typing_key=0, receipt_key=0, account_data_key=0, push_rules_key=0, to_device_key=0, device_list_key=0, groups_key=0, ) return events[:limit], next_token
def wait_for_events(self, user, rooms, timeout, callback, from_token=StreamToken("s0", "0", "0")): """Wait until the callback returns a non empty response or the timeout fires. """ user = str(user) user_stream = self.user_to_user_stream.get(user) if user_stream is None: appservice = yield self.store.get_app_service_by_user_id(user) current_token = yield self.event_sources.get_current_token() rooms = yield self.store.get_rooms_for_user(user) rooms = [room.room_id for room in rooms] user_stream = _NotifierUserStream( user=user, rooms=rooms, appservice=appservice, current_token=current_token, time_now_ms=self.clock.time_msec(), ) self._register_with_keys(user_stream) result = None if timeout: # Will be set to a _NotificationListener that we'll be waiting on. # Allows us to cancel it. listener = None def timed_out(): if listener: listener.deferred.cancel() timer = self.clock.call_later(timeout / 1000., timed_out) prev_token = from_token while not result: try: current_token = user_stream.current_token result = yield callback(prev_token, current_token) if result: break # Now we wait for the _NotifierUserStream to be told there # is a new token. # We need to supply the token we supplied to callback so # that we don't miss any current_token updates. prev_token = current_token listener = user_stream.new_listener(prev_token) yield listener.deferred except defer.CancelledError: break self.clock.cancel_call_later(timer, ignore_errs=True) else: current_token = user_stream.current_token result = yield callback(from_token, current_token) defer.returnValue(result)