bump sync ver to 7 and change meta return value

- /sync/meta now returns a dictionary
- it includes the following extra fields
- msg: if non-empty, show this message at the end of the sync
- cont: if false, show above message and abort sync
- uname: the user's email address, so it can be stored by the local client to
  show users who have forgotten which email address they used. in the future
  this will be saved only when logging in, so do a conditional access on it
This commit is contained in:
Damien Elmes 2013-10-04 06:09:28 +09:00
parent b55761190f
commit f29a04ae29
4 changed files with 56 additions and 13 deletions

View file

@ -47,7 +47,7 @@ SCHEMA_VERSION = 11
SYNC_ZIP_SIZE = int(2.5*1024*1024) SYNC_ZIP_SIZE = int(2.5*1024*1024)
SYNC_ZIP_COUNT = 100 SYNC_ZIP_COUNT = 100
SYNC_URL = os.environ.get("SYNC_URL") or "https://ankiweb.net/sync/" SYNC_URL = os.environ.get("SYNC_URL") or "https://ankiweb.net/sync/"
SYNC_VER = 6 SYNC_VER = 7
HELP_SITE="http://ankisrs.net/docs/manual.html" HELP_SITE="http://ankisrs.net/docs/manual.html"

View file

@ -90,17 +90,39 @@ class Syncer(object):
self.server = server self.server = server
def sync(self): def sync(self):
"Returns 'noChanges', 'fullSync', or 'success'." "Returns 'noChanges', 'fullSync', 'success', etc"
self.syncMsg = ""
self.uname = ""
# if the deck has any pending changes, flush them first and bump mod # if the deck has any pending changes, flush them first and bump mod
# time # time
self.col.save() self.col.save()
# step 1: login & metadata # step 1: login & metadata
runHook("sync", "login") runHook("sync", "login")
ret = self.server.meta() meta = self.server.meta()
if not ret: if not meta:
return "badAuth" return "badAuth"
self.rmod, rscm, self.maxUsn, rts, self.mediaUsn = ret rscm = meta['scm']
self.lmod, lscm, self.minUsn, lts, dummy = self.meta() rts = meta['ts']
self.rmod = meta['mod']
self.maxUsn = meta['usn']
self.mediaUsn = meta['musn']
self.syncMsg = meta['msg']
# this is a temporary measure to address the problem of users
# forgetting which email address they've used - it will be removed
# when enough time has passed
self.uname = meta.get("uname", "")
# server requested abort?
if not meta['cont']:
return "serverAbort"
else:
# don't abort, but ui should show message after sync finishes
# and require confirmation if it's non-empty
pass
meta = self.meta()
self.lmod = meta['mod']
self.minUsn = meta['usn']
lscm = meta['scm']
lts = meta['ts']
if abs(rts - lts) > 300: if abs(rts - lts) > 300:
return "clockOff" return "clockOff"
if self.lmod == self.rmod: if self.lmod == self.rmod:
@ -154,7 +176,15 @@ class Syncer(object):
return "success" return "success"
def meta(self): def meta(self):
return (self.col.mod, self.col.scm, self.col._usn, intTime(), None) return dict(
mod=self.col.mod,
scm=self.col.scm,
usn=self.col._usn,
ts=intTime(),
musn=0,
msg="",
cont=True
)
def changes(self): def changes(self):
"Bundle up small objects." "Bundle up small objects."

View file

@ -26,6 +26,7 @@ class SyncManager(QObject):
auth = self._getUserPass() auth = self._getUserPass()
if not auth: if not auth:
return return
self.pm.profile['syncUser'] = auth[0]
self._sync(auth) self._sync(auth)
else: else:
self._sync() self._sync()
@ -50,6 +51,10 @@ class SyncManager(QObject):
self.mw.app.processEvents() self.mw.app.processEvents()
self.thread.wait(100) self.thread.wait(100)
self.mw.progress.finish() self.mw.progress.finish()
if self.thread.syncMsg:
showText(self.thread.syncMsg)
if self.thread.uname:
self.pm.profile['syncUser'] = self.thread.uname
def delayedInfo(): def delayedInfo():
if self._didFullUp and not self._didError: if self._didFullUp and not self._didError:
showInfo(_("""\ showInfo(_("""\
@ -270,6 +275,8 @@ class SyncThread(QThread):
return return
self.server = RemoteServer(self.hkey) self.server = RemoteServer(self.hkey)
self.client = Syncer(self.col, self.server) self.client = Syncer(self.col, self.server)
self.syncMsg = ""
self.uname = ""
self.sentTotal = 0 self.sentTotal = 0
self.recvTotal = 0 self.recvTotal = 0
# throttle updates; qt doesn't handle lots of posted events well # throttle updates; qt doesn't handle lots of posted events well
@ -349,8 +356,14 @@ class SyncThread(QThread):
# save and note success state # save and note success state
if ret == "noChanges": if ret == "noChanges":
self.fireEvent("noChanges") self.fireEvent("noChanges")
else: elif ret == "success":
self.fireEvent("success") self.fireEvent("success")
elif ret == "serverAbort":
self.fireEvent("error", self.client.syncMsg)
else:
self.fireEvent("error", "Unknown sync return code.")
self.syncMsg = self.client.syncMsg
self.uname = self.client.uname
# then move on to media sync # then move on to media sync
self._syncMedia() self._syncMedia()

View file

@ -45,11 +45,11 @@ def test_meta():
print "aborting; server offline" print "aborting; server offline"
return return
ts.server.hkey = TEST_HKEY ts.server.hkey = TEST_HKEY
(mod, scm, usn, tstamp, mediaUSN) = ts.server.meta() meta = ts.server.meta()
assert mod assert meta['mod']
assert scm assert meta['scm']
assert mod != ts.client.col.mod assert meta['mod'] != ts.client.col.mod
assert abs(tstamp - time.time()) < 3 assert abs(meta['ts'] - time.time()) < 3
@nose.with_setup(setup_remote) @nose.with_setup(setup_remote)
def test_hkey(): def test_hkey():