First hack at implementing timeouts in typing notification handler

This commit is contained in:
Paul "LeoNerd" Evans 2014-12-10 19:39:01 +00:00
parent 4551afc6d2
commit 9eb819e828
2 changed files with 52 additions and 6 deletions

View file

@ -43,7 +43,8 @@ class TypingNotificationHandler(BaseHandler):
self.federation.register_edu_handler("m.typing", self._recv_edu) self.federation.register_edu_handler("m.typing", self._recv_edu)
self._member_typing_until = {} self._member_typing_until = {} # clock time we expect to stop
self._member_typing_timer = {} # deferreds to manage theabove
@defer.inlineCallbacks @defer.inlineCallbacks
def started_typing(self, target_user, auth_user, room_id, timeout): def started_typing(self, target_user, auth_user, room_id, timeout):
@ -58,7 +59,13 @@ class TypingNotificationHandler(BaseHandler):
was_present = member in self._member_typing_until was_present = member in self._member_typing_until
if member in self._member_typing_timer:
self.clock.cancel_call_later(self._member_typing_timer[member])
self._member_typing_until[member] = until self._member_typing_until[member] = until
self._member_typing_timer[member] = self.clock.call_later(
timeout / 1000, lambda: self._stopped_typing(member)
)
if was_present: if was_present:
# No point sending another notification # No point sending another notification
@ -80,16 +87,25 @@ class TypingNotificationHandler(BaseHandler):
member = RoomMember(room_id=room_id, user=target_user) member = RoomMember(room_id=room_id, user=target_user)
yield self._stopped_typing(member)
@defer.inlineCallbacks
def _stopped_typing(self, member):
if member not in self._member_typing_until: if member not in self._member_typing_until:
# No point # No point
defer.returnValue(None) defer.returnValue(None)
yield self._push_update( yield self._push_update(
room_id=room_id, room_id=member.room_id,
user=target_user, user=member.user,
typing=False, typing=False,
) )
del self._member_typing_until[member]
self.clock.cancel_call_later(self._member_typing_timer[member])
del self._member_typing_timer[member]
@defer.inlineCallbacks @defer.inlineCallbacks
def _push_update(self, room_id, user, typing): def _push_update(self, room_id, user, typing):
localusers = set() localusers = set()

View file

@ -238,9 +238,11 @@ class TypingNotificationsTestCase(unittest.TestCase):
# Gut-wrenching # Gut-wrenching
from synapse.handlers.typing import RoomMember from synapse.handlers.typing import RoomMember
self.handler._member_typing_until[ member = RoomMember(self.room_id, self.u_apple)
RoomMember(self.room_id, self.u_apple) self.handler._member_typing_until[member] = 1002000
] = 1002000 self.handler._member_typing_timer[member] = (
self.clock.call_later(1002, lambda: 0)
)
yield self.handler.stopped_typing( yield self.handler.stopped_typing(
target_user=self.u_apple, target_user=self.u_apple,
@ -256,3 +258,31 @@ class TypingNotificationsTestCase(unittest.TestCase):
]) ])
yield put_json.await_calls() yield put_json.await_calls()
@defer.inlineCallbacks
def test_typing_timeout(self):
self.room_members = [self.u_apple, self.u_banana]
yield self.handler.started_typing(
target_user=self.u_apple,
auth_user=self.u_apple,
room_id=self.room_id,
timeout=10000,
)
self.mock_update_client.assert_has_calls([
call(observer_user=self.u_banana,
observed_user=self.u_apple,
room_id=self.room_id,
typing=True),
])
self.mock_update_client.reset_mock()
self.clock.advance_time(11)
self.mock_update_client.assert_has_calls([
call(observer_user=self.u_banana,
observed_user=self.u_apple,
room_id=self.room_id,
typing=False),
])