Rename API-visible 'mtime' presence field to 'last_active'; slightly different semantics

This commit is contained in:
Paul "LeoNerd" Evans 2014-09-01 15:38:37 +01:00
parent 26a95988da
commit 468d94c920
4 changed files with 82 additions and 41 deletions

View File

@ -52,6 +52,13 @@ def partitionbool(l, func):
class PresenceHandler(BaseHandler): class PresenceHandler(BaseHandler):
STATE_LEVELS = {
PresenceState.OFFLINE: 0,
PresenceState.UNAVAILABLE: 1,
PresenceState.ONLINE: 2,
PresenceState.FREE_FOR_CHAT: 3,
}
def __init__(self, hs): def __init__(self, hs):
super(PresenceHandler, self).__init__(hs) super(PresenceHandler, self).__init__(hs)
@ -173,20 +180,24 @@ class PresenceHandler(BaseHandler):
observed_user=target_user observed_user=target_user
) )
if visible: if not visible:
state = yield self.store.get_presence_state(
target_user.localpart
)
state["presence"] = state["state"]
else:
raise SynapseError(404, "Presence information not visible") raise SynapseError(404, "Presence information not visible")
state = yield self.store.get_presence_state(target_user.localpart)
if "mtime" in state:
del state["mtime"]
state["presence"] = state["state"]
if target_user in self._user_cachemap:
state["last_active"] = (
self._user_cachemap[target_user].get_state()["last_active"]
)
else: else:
# TODO(paul): Have remote server send us permissions set # TODO(paul): Have remote server send us permissions set
state = self._get_or_offline_usercache(target_user).get_state() state = self._get_or_offline_usercache(target_user).get_state()
if "mtime" in state and (state["mtime"] is not None): if "last_active" in state:
state["mtime_age"] = int( state["last_active_ago"] = int(
self.clock.time_msec() - state.pop("mtime") self.clock.time_msec() - state.pop("last_active")
) )
defer.returnValue(state) defer.returnValue(state)
@ -203,7 +214,6 @@ class PresenceHandler(BaseHandler):
if target_user != auth_user: if target_user != auth_user:
raise AuthError(400, "Cannot set another user's displayname") raise AuthError(400, "Cannot set another user's displayname")
# TODO(paul): Sanity-check 'state'
if "status_msg" not in state: if "status_msg" not in state:
state["status_msg"] = None state["status_msg"] = None
@ -217,12 +227,21 @@ class PresenceHandler(BaseHandler):
if "state" in state: if "state" in state:
state["presence"] = state.pop("state") state["presence"] = state.pop("state")
if state["presence"] not in self.STATE_LEVELS:
raise SynapseError(400, "'%s' is not a valid presence state" %
state["presence"]
)
logger.debug("Updating presence state of %s to %s", logger.debug("Updating presence state of %s to %s",
target_user.localpart, state["presence"]) target_user.localpart, state["presence"])
state_to_store = dict(state) state_to_store = dict(state)
state_to_store["state"] = state_to_store.pop("presence") state_to_store["state"] = state_to_store.pop("presence")
statuscache=self._get_or_offline_usercache(target_user)
was_level = self.STATE_LEVELS[statuscache.get_state()["presence"]]
now_level = self.STATE_LEVELS[state["presence"]]
yield defer.DeferredList([ yield defer.DeferredList([
self.store.set_presence_state( self.store.set_presence_state(
target_user.localpart, state_to_store target_user.localpart, state_to_store
@ -232,7 +251,8 @@ class PresenceHandler(BaseHandler):
), ),
]) ])
state["mtime"] = self.clock.time_msec() if now_level > was_level:
state["last_active"] = self.clock.time_msec()
now_online = state["presence"] != PresenceState.OFFLINE now_online = state["presence"] != PresenceState.OFFLINE
was_polling = target_user in self._user_cachemap was_polling = target_user in self._user_cachemap
@ -391,9 +411,9 @@ class PresenceHandler(BaseHandler):
observed_user = self.hs.parse_userid(p.pop("observed_user_id")) observed_user = self.hs.parse_userid(p.pop("observed_user_id"))
p["observed_user"] = observed_user p["observed_user"] = observed_user
p.update(self._get_or_offline_usercache(observed_user).get_state()) p.update(self._get_or_offline_usercache(observed_user).get_state())
if "mtime" in p: if "last_active" in p:
p["mtime_age"] = int( p["last_active_ago"] = int(
self.clock.time_msec() - p.pop("mtime") self.clock.time_msec() - p.pop("last_active")
) )
defer.returnValue(presence) defer.returnValue(presence)
@ -582,16 +602,22 @@ class PresenceHandler(BaseHandler):
def _push_presence_remote(self, user, destination, state=None): def _push_presence_remote(self, user, destination, state=None):
if state is None: if state is None:
state = yield self.store.get_presence_state(user.localpart) state = yield self.store.get_presence_state(user.localpart)
del state["mtime"]
state["presence"] = state["state"] state["presence"] = state["state"]
if user in self._user_cachemap:
state["last_active"] = (
self._user_cachemap[user].get_state()["last_active"]
)
yield self.distributor.fire( yield self.distributor.fire(
"collect_presencelike_data", user, state "collect_presencelike_data", user, state
) )
if "mtime" in state: if "last_active" in state:
state = dict(state) state = dict(state)
state["mtime_age"] = int( state["last_active_ago"] = int(
self.clock.time_msec() - state.pop("mtime") self.clock.time_msec() - state.pop("last_active")
) )
user_state = { user_state = {
@ -636,9 +662,9 @@ class PresenceHandler(BaseHandler):
state["presence"] = state["state"] state["presence"] = state["state"]
del state["state"] del state["state"]
if "mtime_age" in state: if "last_active_ago" in state:
state["mtime"] = int( state["last_active"] = int(
self.clock.time_msec() - state.pop("mtime_age") self.clock.time_msec() - state.pop("last_active_ago")
) )
statuscache = self._get_or_make_usercache(user) statuscache = self._get_or_make_usercache(user)
@ -846,9 +872,9 @@ class UserPresenceCache(object):
content = self.get_state() content = self.get_state()
content["user_id"] = user.to_string() content["user_id"] = user.to_string()
if "mtime" in content: if "last_active" in content:
content["mtime_age"] = int( content["last_active_ago"] = int(
clock.time_msec() - content.pop("mtime") clock.time_msec() - content.pop("last_active")
) )
return {"type": "m.presence", "content": content} return {"type": "m.presence", "content": content}

View File

@ -213,7 +213,7 @@ class PresenceStateTestCase(unittest.TestCase):
state={ state={
"presence": UNAVAILABLE, "presence": UNAVAILABLE,
"status_msg": "Away", "status_msg": "Away",
"mtime": 1000000, # MockClock "last_active": 1000000, # MockClock
}) })
yield self.handler.set_state( yield self.handler.set_state(
@ -621,6 +621,9 @@ class PresencePushTestCase(unittest.TestCase):
# TODO(paul): Gut-wrenching # TODO(paul): Gut-wrenching
self.handler._user_cachemap[self.u_apple] = UserPresenceCache() self.handler._user_cachemap[self.u_apple] = UserPresenceCache()
self.handler._user_cachemap[self.u_apple].update(
{"presence": OFFLINE}, serial=0
)
apple_set = self.handler._local_pushmap.setdefault("apple", set()) apple_set = self.handler._local_pushmap.setdefault("apple", set())
apple_set.add(self.u_banana) apple_set.add(self.u_banana)
apple_set.add(self.u_clementine) apple_set.add(self.u_clementine)
@ -640,7 +643,7 @@ class PresencePushTestCase(unittest.TestCase):
"user_id": "@apple:test", "user_id": "@apple:test",
"presence": ONLINE, "presence": ONLINE,
"state": ONLINE, "state": ONLINE,
"mtime_age": 0, "last_active_ago": 0,
}}, }},
], ],
) )
@ -673,7 +676,7 @@ class PresencePushTestCase(unittest.TestCase):
{"observed_user": self.u_banana, {"observed_user": self.u_banana,
"presence": ONLINE, "presence": ONLINE,
"state": ONLINE, "state": ONLINE,
"mtime_age": 2000}, "last_active_ago": 2000},
{"observed_user": self.u_clementine, {"observed_user": self.u_clementine,
"presence": OFFLINE, "presence": OFFLINE,
"state": OFFLINE}, "state": OFFLINE},
@ -690,7 +693,7 @@ class PresencePushTestCase(unittest.TestCase):
"user_id": "@banana:test", "user_id": "@banana:test",
"presence": ONLINE, "presence": ONLINE,
"state": ONLINE, "state": ONLINE,
"mtime_age": 2000 "last_active_ago": 2000
}}, }},
] ]
) )
@ -707,7 +710,7 @@ class PresencePushTestCase(unittest.TestCase):
{"user_id": "@apple:test", {"user_id": "@apple:test",
"presence": u"online", "presence": u"online",
"state": u"online", "state": u"online",
"mtime_age": 0}, "last_active_ago": 0},
], ],
} }
) )
@ -723,6 +726,9 @@ class PresencePushTestCase(unittest.TestCase):
# TODO(paul): Gut-wrenching # TODO(paul): Gut-wrenching
self.handler._user_cachemap[self.u_apple] = UserPresenceCache() self.handler._user_cachemap[self.u_apple] = UserPresenceCache()
self.handler._user_cachemap[self.u_apple].update(
{"presence": OFFLINE}, serial=0
)
apple_set = self.handler._remote_sendmap.setdefault("apple", set()) apple_set = self.handler._remote_sendmap.setdefault("apple", set())
apple_set.add(self.u_potato.domain) apple_set.add(self.u_potato.domain)
@ -750,7 +756,7 @@ class PresencePushTestCase(unittest.TestCase):
"push": [ "push": [
{"user_id": "@potato:remote", {"user_id": "@potato:remote",
"state": "online", "state": "online",
"mtime_age": 1000}, "last_active_ago": 1000},
], ],
} }
) )
@ -767,7 +773,7 @@ class PresencePushTestCase(unittest.TestCase):
"user_id": "@potato:remote", "user_id": "@potato:remote",
"presence": ONLINE, "presence": ONLINE,
"state": ONLINE, "state": ONLINE,
"mtime_age": 1000, "last_active_ago": 1000,
}} }}
] ]
) )
@ -777,7 +783,7 @@ class PresencePushTestCase(unittest.TestCase):
state = yield self.handler.get_state(self.u_potato, self.u_apple) state = yield self.handler.get_state(self.u_potato, self.u_apple)
self.assertEquals( self.assertEquals(
{"state": ONLINE, "presence": ONLINE, "mtime_age": 3000}, {"state": ONLINE, "presence": ONLINE, "last_active_ago": 3000},
state state
) )
@ -792,7 +798,7 @@ class PresencePushTestCase(unittest.TestCase):
self.handler._user_cachemap[self.u_clementine].update( self.handler._user_cachemap[self.u_clementine].update(
{ {
"presence": PresenceState.ONLINE, "presence": PresenceState.ONLINE,
"mtime": self.clock.time_msec(), "last_active": self.clock.time_msec(),
}, self.u_clementine }, self.u_clementine
) )
@ -811,7 +817,7 @@ class PresencePushTestCase(unittest.TestCase):
"user_id": "@clementine:test", "user_id": "@clementine:test",
"presence": ONLINE, "presence": ONLINE,
"state": ONLINE, "state": ONLINE,
"mtime_age": 0, "last_active_ago": 0,
}} }}
] ]
) )
@ -967,7 +973,8 @@ class PresencePollingTestCase(unittest.TestCase):
def get_presence_state(user_localpart): def get_presence_state(user_localpart):
return defer.succeed( return defer.succeed(
{"state": self.current_user_state[user_localpart], {"state": self.current_user_state[user_localpart],
"status_msg": None} "status_msg": None,
"mtime": 123456000}
) )
self.datastore.get_presence_state = get_presence_state self.datastore.get_presence_state = get_presence_state

View File

@ -166,7 +166,11 @@ class PresenceProfilelikeDataTestCase(unittest.TestCase):
# TODO(paul): Gut-wrenching # TODO(paul): Gut-wrenching
from synapse.handlers.presence import UserPresenceCache from synapse.handlers.presence import UserPresenceCache
self.handlers.presence_handler._user_cachemap[self.u_apple] = ( self.handlers.presence_handler._user_cachemap[self.u_apple] = (
UserPresenceCache()) UserPresenceCache()
)
self.handlers.presence_handler._user_cachemap[self.u_apple].update(
{"presence": OFFLINE}, serial=0
)
apple_set = self.handlers.presence_handler._local_pushmap.setdefault( apple_set = self.handlers.presence_handler._local_pushmap.setdefault(
"apple", set()) "apple", set())
apple_set.add(self.u_banana) apple_set.add(self.u_banana)
@ -184,7 +188,7 @@ class PresenceProfilelikeDataTestCase(unittest.TestCase):
{"observed_user": self.u_banana, {"observed_user": self.u_banana,
"presence": ONLINE, "presence": ONLINE,
"state": ONLINE, "state": ONLINE,
"mtime_age": 0, "last_active_ago": 0,
"displayname": "Frank", "displayname": "Frank",
"avatar_url": "http://foo"}, "avatar_url": "http://foo"},
{"observed_user": self.u_clementine, {"observed_user": self.u_clementine,
@ -202,7 +206,7 @@ class PresenceProfilelikeDataTestCase(unittest.TestCase):
statuscache = self.mock_update_client.call_args[1]["statuscache"] statuscache = self.mock_update_client.call_args[1]["statuscache"]
self.assertEquals({ self.assertEquals({
"presence": ONLINE, "presence": ONLINE,
"mtime": 1000000, # MockClock "last_active": 1000000, # MockClock
"displayname": "Frank", "displayname": "Frank",
"avatar_url": "http://foo", "avatar_url": "http://foo",
}, statuscache.state) }, statuscache.state)
@ -225,7 +229,7 @@ class PresenceProfilelikeDataTestCase(unittest.TestCase):
statuscache = self.mock_update_client.call_args[1]["statuscache"] statuscache = self.mock_update_client.call_args[1]["statuscache"]
self.assertEquals({ self.assertEquals({
"presence": ONLINE, "presence": ONLINE,
"mtime": 1000000, # MockClock "last_active": 1000000, # MockClock
"displayname": "I am an Apple", "displayname": "I am an Apple",
"avatar_url": "http://foo", "avatar_url": "http://foo",
}, statuscache.state) }, statuscache.state)
@ -243,7 +247,11 @@ class PresenceProfilelikeDataTestCase(unittest.TestCase):
# TODO(paul): Gut-wrenching # TODO(paul): Gut-wrenching
from synapse.handlers.presence import UserPresenceCache from synapse.handlers.presence import UserPresenceCache
self.handlers.presence_handler._user_cachemap[self.u_apple] = ( self.handlers.presence_handler._user_cachemap[self.u_apple] = (
UserPresenceCache()) UserPresenceCache()
)
self.handlers.presence_handler._user_cachemap[self.u_apple].update(
{"presence": OFFLINE}, serial=0
)
apple_set = self.handlers.presence_handler._remote_sendmap.setdefault( apple_set = self.handlers.presence_handler._remote_sendmap.setdefault(
"apple", set()) "apple", set())
apple_set.add(self.u_potato.domain) apple_set.add(self.u_potato.domain)
@ -259,7 +267,7 @@ class PresenceProfilelikeDataTestCase(unittest.TestCase):
{"user_id": "@apple:test", {"user_id": "@apple:test",
"presence": "online", "presence": "online",
"state": "online", "state": "online",
"mtime_age": 0, "last_active_ago": 0,
"displayname": "Frank", "displayname": "Frank",
"avatar_url": "http://foo"}, "avatar_url": "http://foo"},
], ],

View File

@ -330,6 +330,6 @@ class PresenceEventStreamTestCase(unittest.TestCase):
"presence": ONLINE, "presence": ONLINE,
"state": ONLINE, "state": ONLINE,
"displayname": "Frank", "displayname": "Frank",
"mtime_age": 0, "last_active_ago": 0,
}}, }},
]}, response) ]}, response)