Swift/Cloudkit:拉取时处理用户更改
Swift/Cloudkit: Handling user-changes while pulling
我从 this Whosebug question and from the Basic CloudKit Workflow 了解到,与 Cloudkit 同步的普遍方式是先推送本地更改,然后拉取远程更改,这样我就可以在推送期间通过看到更改失败来检测更改,因为服务器上的更新版本。
但是如果我拉得更久一点会怎样
- 并且用户进行了更改并且用户更改使提取的数据无效?
- 用户所做的更改由于文件已删除而变得过时?
一个示例是,在用户对 to-be-uploaded stack
上更改的文件夹中的文件进行编辑后,拉取删除文件夹。因此,拉动当前有效,而用户已经将操作推送到更改列表上,因为更改已经在本地完成。
我想到的一种处理方法是在我从服务器拉取时禁止任何用户更改。然后我根据拉动更改 UI 并再次启用更改。
但我不知道推送需要多长时间,所以UI 一段时间无法更改内容可能是糟糕的用户体验。
其他人如何处理(或避免)使用户所做的更改无效的拉动?
我试图避免在拉动时覆盖已完成的用户更改。例子:
我有一个文件,当我下载另一个版本的文件时,用户保存了对它的更改。
本地用户更改已经在排队。
因此,一旦我完成拉取并开始推送用户本地更改,我就会推送一个不再反映本地缓存的更改。
当我尝试推送它时肯定会出现版本错误,是否需要在本地和服务器上合并更改?
为了避免这个问题,我可以等待更改排队,但将其命名为 proposed
更改,我在拉取过程中识别并可以采取行动。如果拉取的更改与 proposed
不兼容,我可能会拒绝 proposed
更改并通知用户冲突。
注意:此问题与 CKError.Code.serverChangedError
不同,因为它仅与拉取期间所做的更改相关。
TLDR:不应允许拉取、推送和本地更改同时发生。
- 推送期间的本地更改是可以的,它们只是添加到下一批要推送的更改中。我必须清空 push-local-changes 批处理并将本地缓存锁定为 proposed-mode 在我推送之前,因此避免了问题。
- 拉取期间的本地更改成为提议的更改,必须在合并拉取数据期间或之后确定它们的有效性,并通过通知用户采取行动。
将建议的更改链接到本地缓存对象是必要的,这样拉式合并可以通知建议的更改并将对象更改存储在其中,因此建议的更改可能无效。
链接到提议的更改的另一种方法是在对象中有一个版本号,并且在每次更改时增加版本号(尤其是在拉式合并更改期间)。在创建时,提议的更改保存它要更改的对象的版本号。在评估提议的更改时拉合并后,可以通过将对象内的版本号与存储在对象的提议更改中的版本号进行比较来评估。
————————————
另一种选择是 - 在拉取所有更改后 - 不直接合并它们,而是先推送更改,直到不再有本地更改,然后阻止本地更改并合并拉取的更改。
我不必担心拉合并冲突,因为我已经将推送中的用户更改调整为服务器更改,因此拉不能使刚刚推送的用户所做的更改无效。
————————
备选方案 3 是:获取之前拉取的所有内容,直到用户在拉取期间未进行任何更改。然后在合并获取的记录时很快锁定数据库。
注意:上传并修复了记录的合并冲突后,可以丢弃记录的远程更改。
我从 this Whosebug question and from the Basic CloudKit Workflow 了解到,与 Cloudkit 同步的普遍方式是先推送本地更改,然后拉取远程更改,这样我就可以在推送期间通过看到更改失败来检测更改,因为服务器上的更新版本。
但是如果我拉得更久一点会怎样
- 并且用户进行了更改并且用户更改使提取的数据无效?
- 用户所做的更改由于文件已删除而变得过时?
一个示例是,在用户对 to-be-uploaded stack
上更改的文件夹中的文件进行编辑后,拉取删除文件夹。因此,拉动当前有效,而用户已经将操作推送到更改列表上,因为更改已经在本地完成。
我想到的一种处理方法是在我从服务器拉取时禁止任何用户更改。然后我根据拉动更改 UI 并再次启用更改。
但我不知道推送需要多长时间,所以UI 一段时间无法更改内容可能是糟糕的用户体验。
其他人如何处理(或避免)使用户所做的更改无效的拉动?
我试图避免在拉动时覆盖已完成的用户更改。例子: 我有一个文件,当我下载另一个版本的文件时,用户保存了对它的更改。
本地用户更改已经在排队。 因此,一旦我完成拉取并开始推送用户本地更改,我就会推送一个不再反映本地缓存的更改。
当我尝试推送它时肯定会出现版本错误,是否需要在本地和服务器上合并更改?
为了避免这个问题,我可以等待更改排队,但将其命名为 proposed
更改,我在拉取过程中识别并可以采取行动。如果拉取的更改与 proposed
不兼容,我可能会拒绝 proposed
更改并通知用户冲突。
注意:此问题与 CKError.Code.serverChangedError
不同,因为它仅与拉取期间所做的更改相关。
TLDR:不应允许拉取、推送和本地更改同时发生。
- 推送期间的本地更改是可以的,它们只是添加到下一批要推送的更改中。我必须清空 push-local-changes 批处理并将本地缓存锁定为 proposed-mode 在我推送之前,因此避免了问题。
- 拉取期间的本地更改成为提议的更改,必须在合并拉取数据期间或之后确定它们的有效性,并通过通知用户采取行动。
将建议的更改链接到本地缓存对象是必要的,这样拉式合并可以通知建议的更改并将对象更改存储在其中,因此建议的更改可能无效。
链接到提议的更改的另一种方法是在对象中有一个版本号,并且在每次更改时增加版本号(尤其是在拉式合并更改期间)。在创建时,提议的更改保存它要更改的对象的版本号。在评估提议的更改时拉合并后,可以通过将对象内的版本号与存储在对象的提议更改中的版本号进行比较来评估。
————————————
另一种选择是 - 在拉取所有更改后 - 不直接合并它们,而是先推送更改,直到不再有本地更改,然后阻止本地更改并合并拉取的更改。
我不必担心拉合并冲突,因为我已经将推送中的用户更改调整为服务器更改,因此拉不能使刚刚推送的用户所做的更改无效。
————————
备选方案 3 是:获取之前拉取的所有内容,直到用户在拉取期间未进行任何更改。然后在合并获取的记录时很快锁定数据库。
注意:上传并修复了记录的合并冲突后,可以丢弃记录的远程更改。