Rename 'mtime' DB field to 'last_active', adjusted semantics

paul/schema_breaking_changes
Paul "LeoNerd" Evans 2014-09-03 17:04:58 +01:00
parent b8906b0ea8
commit 801a551da1
7 changed files with 30 additions and 25 deletions

View File

@ -178,8 +178,6 @@ class PresenceHandler(BaseHandler):
if not visible: if not visible:
raise SynapseError(404, "Presence information not visible") raise SynapseError(404, "Presence information not visible")
state = yield self.store.get_presence_state(target_user.localpart) state = yield self.store.get_presence_state(target_user.localpart)
if "mtime" in state:
del state["mtime"]
if target_user in self._user_cachemap: if target_user in self._user_cachemap:
state["last_active"] = ( state["last_active"] = (
@ -225,12 +223,17 @@ class PresenceHandler(BaseHandler):
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)
statuscache=self._get_or_offline_usercache(target_user) statuscache=self._get_or_offline_usercache(target_user)
was_level = self.STATE_LEVELS[statuscache.get_state()["presence"]] oldstate = statuscache.get_state()
was_level = self.STATE_LEVELS[oldstate["presence"]]
now_level = self.STATE_LEVELS[state["presence"]] now_level = self.STATE_LEVELS[state["presence"]]
if now_level > was_level:
state["last_active"] = self.clock.time_msec()
state_to_store = dict(state)
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
@ -240,9 +243,6 @@ class PresenceHandler(BaseHandler):
), ),
]) ])
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
@ -593,7 +593,6 @@ 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"]
if user in self._user_cachemap: if user in self._user_cachemap:
state["last_active"] = ( state["last_active"] = (
@ -881,8 +880,6 @@ class UserPresenceCache(object):
self.serial = None self.serial = None
def update(self, state, serial): def update(self, state, serial):
assert("mtime_age" not in state)
self.state.update(state) self.state.update(state)
# Delete keys that are now 'None' # Delete keys that are now 'None'
for k in self.state.keys(): for k in self.state.keys():

View File

@ -35,16 +35,14 @@ class PresenceStore(SQLBaseStore):
return self._simple_select_one( return self._simple_select_one(
table="presence", table="presence",
keyvalues={"user_id": user_localpart}, keyvalues={"user_id": user_localpart},
retcols=["presence", "status_msg", "mtime"], retcols=["presence", "status_msg", "last_active"],
) )
def set_presence_state(self, user_localpart, new_state): def set_presence_state(self, user_localpart, new_state):
return self._simple_update_one( return self._simple_update_one(
table="presence", table="presence",
keyvalues={"user_id": user_localpart}, keyvalues={"user_id": user_localpart},
updatevalues={"presence": new_state["presence"], updatevalues=new_state,
"status_msg": new_state["status_msg"],
"mtime": self._clock.time_msec()},
retcols=["presence"], retcols=["presence"],
) )

View File

@ -20,12 +20,13 @@ CREATE TABLE NEW_presence(
user_id INTEGER NOT NULL, user_id INTEGER NOT NULL,
presence INTEGER, presence INTEGER,
status_msg TEXT, status_msg TEXT,
mtime INTEGER, last_active INTEGER,
FOREIGN KEY(user_id) REFERENCES users(id) FOREIGN KEY(user_id) REFERENCES users(id)
); );
-- rename the 'state' field to 'presence' -- rename the 'state' field to 'presence'; migrate the old 'mtime' field into
INSERT INTO NEW_presence (user_id, presence, status_msg, mtime) -- the new 'last_active' field
INSERT INTO NEW_presence (user_id, presence, status_msg, last_active)
SELECT user_id, state, status_msg, mtime FROM presence; SELECT user_id, state, status_msg, mtime FROM presence;
DROP TABLE presence; DROP TABLE presence;

View File

@ -16,7 +16,7 @@ CREATE TABLE IF NOT EXISTS presence(
user_id INTEGER NOT NULL, user_id INTEGER NOT NULL,
presence INTEGER, presence INTEGER,
status_msg TEXT, status_msg TEXT,
mtime INTEGER, -- miliseconds since last state change last_active INTEGER,
FOREIGN KEY(user_id) REFERENCES users(id) FOREIGN KEY(user_id) REFERENCES users(id)
); );

View File

@ -208,7 +208,10 @@ class PresenceStateTestCase(unittest.TestCase):
state={"presence": UNAVAILABLE, "status_msg": "Away"}) state={"presence": UNAVAILABLE, "status_msg": "Away"})
mocked_set.assert_called_with("apple", mocked_set.assert_called_with("apple",
{"presence": UNAVAILABLE, "status_msg": "Away"} {"presence": UNAVAILABLE,
"status_msg": "Away",
"last_active": 1000000, # MockClock
}
) )
self.mock_start.assert_called_with(self.u_apple, self.mock_start.assert_called_with(self.u_apple,
state={ state={
@ -1045,7 +1048,7 @@ class PresencePollingTestCase(unittest.TestCase):
return defer.succeed( return defer.succeed(
{"presence": self.current_user_state[user_localpart], {"presence": self.current_user_state[user_localpart],
"status_msg": None, "status_msg": None,
"mtime": 123456000} "last_active": 500000}
) )
self.datastore.get_presence_state = get_presence_state self.datastore.get_presence_state = get_presence_state
@ -1249,7 +1252,8 @@ class PresencePollingTestCase(unittest.TestCase):
"push": [ "push": [
{"user_id": "@banana:test", {"user_id": "@banana:test",
"presence": "offline", "presence": "offline",
"status_msg": None}, "status_msg": None,
"last_active_ago": 500000},
], ],
}, },
), ),

View File

@ -151,7 +151,9 @@ class PresenceProfilelikeDataTestCase(unittest.TestCase):
state={"presence": UNAVAILABLE, "status_msg": "Away"}) state={"presence": UNAVAILABLE, "status_msg": "Away"})
mocked_set.assert_called_with("apple", mocked_set.assert_called_with("apple",
{"presence": UNAVAILABLE, "status_msg": "Away"} {"presence": UNAVAILABLE,
"status_msg": "Away",
"last_active": 1000000}
) )
@defer.inlineCallbacks @defer.inlineCallbacks

View File

@ -21,7 +21,7 @@ from twisted.internet import defer
from mock import Mock from mock import Mock
import logging import logging
from ..utils import MockHttpResource from ..utils import MockHttpResource, MockClock
from synapse.api.constants import PresenceState from synapse.api.constants import PresenceState
from synapse.handlers.presence import PresenceHandler from synapse.handlers.presence import PresenceHandler
@ -51,6 +51,7 @@ class PresenceStateTestCase(unittest.TestCase):
self.mock_resource = MockHttpResource(prefix=PATH_PREFIX) self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
hs = HomeServer("test", hs = HomeServer("test",
clock=MockClock(),
db_pool=None, db_pool=None,
datastore=Mock(spec=[ datastore=Mock(spec=[
"get_presence_state", "get_presence_state",
@ -115,7 +116,9 @@ class PresenceStateTestCase(unittest.TestCase):
self.assertEquals(200, code) self.assertEquals(200, code)
mocked_set.assert_called_with("apple", mocked_set.assert_called_with("apple",
{"presence": UNAVAILABLE, "status_msg": "Away"} {"presence": UNAVAILABLE,
"status_msg": "Away",
"last_active": 1000000}
) )