force a full sync when fields or templates changed without schema mod

This is not an ideal solution and will not catch repositioned fields
or templates, but is at least an improvement over the previous behaviour.

https://github.com/dae/anki/pull/349#issuecomment-547236285
This commit is contained in:
Damien Elmes 2019-10-30 10:17:09 +10:00
parent fc713d2010
commit 9a6f2be2b6

View File

@ -22,6 +22,9 @@ HTTP_TIMEOUT = 90
HTTP_PROXY = None HTTP_PROXY = None
HTTP_BUF_SIZE = 64*1024 HTTP_BUF_SIZE = 64*1024
class UnexpectedSchemaChange(Exception):
pass
# Incremental syncing # Incremental syncing
########################################################################## ##########################################################################
@ -95,7 +98,11 @@ class Syncer:
# ...and small objects # ...and small objects
lchg = self.changes() lchg = self.changes()
rchg = self.server.applyChanges(changes=lchg) rchg = self.server.applyChanges(changes=lchg)
self.mergeChanges(lchg, rchg) try:
self.mergeChanges(lchg, rchg)
except UnexpectedSchemaChange:
self.server.abort()
return self._forceFullSync()
# step 3: stream large tables from server # step 3: stream large tables from server
runHook("sync", "server") runHook("sync", "server")
while 1: while 1:
@ -119,17 +126,20 @@ class Syncer:
c = self.sanityCheck() c = self.sanityCheck()
ret = self.server.sanityCheck2(client=c) ret = self.server.sanityCheck2(client=c)
if ret['status'] != "ok": if ret['status'] != "ok":
# roll back and force full sync return self._forceFullSync()
self.col.rollback()
self.col.modSchema(False)
self.col.save()
return "sanityCheckFailed"
# finalize # finalize
runHook("sync", "finalize") runHook("sync", "finalize")
mod = self.server.finish() mod = self.server.finish()
self.finish(mod) self.finish(mod)
return "success" return "success"
def _forceFullSync(self):
# roll back and force full sync
self.col.rollback()
self.col.modSchema(False)
self.col.save()
return "sanityCheckFailed"
def _gravesChunk(self, graves): def _gravesChunk(self, graves):
lim = 250 lim = 250
chunk = dict(notes=[], cards=[], decks=[]) chunk = dict(notes=[], cards=[], decks=[])
@ -330,6 +340,14 @@ from notes where %s""" % d)
l = self.col.models.get(r['id']) l = self.col.models.get(r['id'])
# if missing locally or server is newer, update # if missing locally or server is newer, update
if not l or r['mod'] > l['mod']: if not l or r['mod'] > l['mod']:
# This is a hack to detect when the note type has been altered
# in an import without a full sync being forced. A future
# syncing algorithm should handle this in a better way.
if l:
if len(l['flds']) != len(r['flds']):
raise UnexpectedSchemaChange()
if len(l['tmpls']) != len(r['tmpls']):
raise UnexpectedSchemaChange()
self.col.models.update(r) self.col.models.update(r)
# Decks # Decks