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_COUNT = 100
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"

View File

@ -90,17 +90,39 @@ class Syncer(object):
self.server = server
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
# time
self.col.save()
# step 1: login & metadata
runHook("sync", "login")
ret = self.server.meta()
if not ret:
meta = self.server.meta()
if not meta:
return "badAuth"
self.rmod, rscm, self.maxUsn, rts, self.mediaUsn = ret
self.lmod, lscm, self.minUsn, lts, dummy = self.meta()
rscm = meta['scm']
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:
return "clockOff"
if self.lmod == self.rmod:
@ -154,7 +176,15 @@ class Syncer(object):
return "success"
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):
"Bundle up small objects."

View File

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

View File

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