客户端重置 - .NET SDK
在此页面上
Overview
10.17.0 版本新增。
客户端重置错误是指客户端域无法与应用程序后端同步数据的情况。处于此状态的客户端可以继续运行并在本地保存数据,但在执行客户端重置之前无法发送或接收同步变更集。 Realm SDK 提供了在大多数情况下自动处理客户端重置的方法。
客户端重置策略
当服务器的历史记录与客户端的历史记录不兼容时,就会出现客户端重置情况。 客户客户端重置中描述了客户端重置的最常见原因。
在 .NET SDK 中,可以在FlexibleSyncConfiguration和PartitionSyncConfiguration中指定客户端重置策略。 ClientResetHandler属性可以设置为以下之一:
Handler | 策略 | 注意 |
---|---|---|
恢复所有未同步的本地更改 | 如果恢复失败,此处理程序将回退到 DiscardUnsyncedChangesHandler ,从而删除所有未同步的本地更改。 如果DiscardUnsyncedChangesHandler 恢复失败,处理程序将回退到ManualRecoveryHandler ,这需要您实施手动恢复策略。 | |
恢复所有未同步的本地更改 | 如果恢复失败,此处理程序将回退到 ManualRecoveryHandler ,这需要您实施手动恢复策略。 | |
丢弃未同步的更改 | 此策略会永久删除自上次成功同步以来所做的所有本地未同步更改。 | |
手动恢复 | 为您提供实施自己的恢复策略的方法。 |
以下部分描述了处理客户端重置的不同策略以及如何使用每个ClientResetHandlers
。
恢复未同步的本地更改
In a client reset that does not involve a breaking schema change, the SDK integrates objects created locally that did not sync before the client reset. 以下规则决定了当后端和客户端都对同一对象进行更改时如何解决冲突:
如果一个对象在服务器上被删除,但在恢复的客户端上被修改,则删除优先,客户端丢弃更新。
如果在恢复的客户端上删除一个对象,但在服务器上没有删除,则客户端应用删除指令。
如果对同一字段的更新发生冲突,则应用客户端更新。
重要
重大更改
恢复进程无法处理中断模式更改。 示例,如果您对一个或多个Realm 对象类进行非累加性更改,则恢复进程将失败。 在这种情况下,用户需要更新其客户端应用。 有关重大更改的更多信息,请参阅重大与非重大更改快速参考。
有两个客户端重置处理程序会尝试自动恢复未同步的本地数据: RecoverOrDiscardUnsyncedChangesHandler
和RecoverUnsyncedChangesHandler
。
RecoverOrDiscardUnsyncedChangesHandler
这是默认处理程序,因为它提供了最稳健的恢复过程。 如果自动恢复进程失败,则会改用“放弃未同步的更改”部分中解释的DiscardLocalReset
策略。 如果该过程失败,则会再次使用“手动恢复”部分中说明的手动重置策略。 此处理程序提供以下回调方法:
OnBeforeReset ,SDK 在客户端重置之前调用。 您可以使用此回调在客户端重置开始之前通知用户。
OnAfterRecovery ,当且仅当自动重置成功完成时,SDK 才会调用。 您可以使用它来通知用户客户端重置已完成。
OnAfterDiscard ,仅当客户端重置失败且丢弃本地策略成功时,SDK 才会调用该函数。 如果丢弃策略失败,则不会调用此回调。
ManualResetFallback ,SDK 仅在自动恢复和丢弃策略失败时调用。 您可以实现此回调来处理重置失败的情况。 此处的逻辑应与针对ManualRecoveryHandler 描述的逻辑类似。
以下示例展示了如何使用每个回调:
var conf = new FlexibleSyncConfiguration(user) { ClientResetHandler = new RecoverOrDiscardUnsyncedChangesHandler { // The following callbacks are optional OnBeforeReset = (beforeReset) => { // Executed before the client reset begins // Can be used to notify the user that a reset is going // to happen }, OnAfterRecovery = (beforeReset, afterReset) => { // Executed after the client reset is complete // Can be used to notify the user that the reset is done }, OnAfterDiscard = (beforeReset, afterReset) => { // Executed if the automatic recovery has failed // but the DiscardUnsyncedChanges fallback has completed // successfully }, ManualResetFallback = (err) => { // Automatic reset failed; handle the reset manually here } } };
RecoverUnsyncedChangesHandler
与RecoverOrDiscardUnsyncedChangesHandler
一样,此处理程序会尝试自动恢复所有未同步的本地更改。 但是,与RecoverOrDiscardUnsyncedChangesHandler
不同,如果自动恢复失败,此处理程序不会回退到DiscardUnsyncedChangesHandler
。 相反,它会改用手动恢复部分中解释的手动重置策略。 该处理程序提供以下回调方法:
OnBeforeReset ,可用于在重置开始之前通知用户。
OnAfterReset ,可用于在重置成功完成时通知用户。
ManualResetFallback ,用于处理实现失败。 此处的逻辑应与针对ManualRecoveryHandler 描述的逻辑类似。
以下示例展示了如何使用每个回调:
var conf = new FlexibleSyncConfiguration(user) { ClientResetHandler = new RecoverUnsyncedChangesHandler { // The following callbacks are optional OnBeforeReset = (beforeReset) => { // Executed before the client reset begins // Can be used to notify the user that a reset is going // to happen }, OnAfterReset = (beforeReset, afterReset) => { // Executed after the client reset is complete // Can be used to notify the user that the reset is done }, ManualResetFallback = (err) => { // Automatic reset failed; handle the reset manually here } } };
丢弃未同步的更改
此策略会永久删除自上次成功同步以来所做的所有本地未同步更改。 如果您选择使用DiscardUnsyncedChangesHandler
,SDK 会将本地域文件恢复到可同步状态,而无需关闭域 ,同时保持通知正常运行。 如果此进程失败,则会转而使用“手动恢复”部分中说明的手动重置策略。 此处理程序提供以下回调方法:
OnBeforeReset ,SDK 在客户端重置之前调用。 您可以使用此回调在重置开始之前通知用户。
OnAfterReset ,当且仅当重置成功完成时,SDK 才会调用。 您可以使用它来通知用户重置完成。
ManualResetFallback ,SDK 在重置失败时调用它。 此处的逻辑应与针对ManualRecoveryHandler 描述的逻辑类似。
以下示例展示了如何实施DiscardUnsyncedChangesHandler
:
{
var config = new FlexibleSyncConfiguration(user);
config.ClientResetHandler = new DiscardUnsyncedChangesHandler()
{
// The following callbacks are optional
OnBeforeReset = (beforeReset) =>
{ // Executed before the client reset begins // Can be used to notify the user that a reset is going // to happen },
OnAfterReset = (beforeReset, afterReset) => { // Executed after the client reset is complete // Can be used to notify the user that the reset is done },
ManualResetFallback = (err) =>
{ // Automatic reset failed; handle the reset manually here }
};
try {
var realm = await Realm.GetInstanceAsync(config); }
catch (Exception ex) { Console.WriteLine($@"Error creating or opening the realm file. {ex.Message}"); }
手动恢复
在大多数情况下,应使用其他策略之一进行客户端重置。 对于需要自定义数据恢复进程的罕见情况,请选择ManualRecoveryHandler处理程序。
注意
回退
虽然手动策略只应在边缘情况下使用,但其他客户端重置处理程序可能会改用手动策略。 在这些处理程序中使用的逻辑与此处描述的逻辑类似。
在ManualRecoveryHandler
中,您可以释放现有 Realm,然后调用InitiateClientReset()方法。
以下示例演示了ManualRecoveryHandler
的实现:
private void SetupRealm()
{
var config = new FlexibleSyncConfiguration(user);
config.ClientResetHandler =
new ManualRecoveryHandler(HandleClientResetError);
var realm = await Realm.GetInstanceAsync(config);
}
private void HandleClientResetError(ClientResetException clientResetException)
{
Console.WriteLine($"Client Reset requested: {clientResetException.Message}");
// Prompt user to perform a client reset immediately. If they don't,
// they won't receive any data from the server until they restart the app
// and all changes they make will be discarded when the app restarts.
var didUserConfirmReset = ShowUserAConfirmationDialog();
if (didUserConfirmReset)
{
// Close the Realm before doing the reset. It must be
// deleted as part of the reset.
fsRealm.Dispose();
// perform the client reset
var didReset = clientResetException.InitiateClientReset();
if (didReset)
{
// Navigate the user back to the main page or reopen the
// the Realm and reinitialize the current page
}
else
{
// Reset failed - notify user that they'll need to
// update the app
}
}
}
测试客户端重置处理
您可以通过终止并重新启用 Device Sync 来手动测试应用程序的客户端重置处理。
当您终止并重新启用 Sync 时,之前使用 Sync 连接的客户端在执行客户端重置之前无法进行连接。 终止同步会从服务器中删除允许客户端同步的元数据。 客户端必须从服务器下载 Realm 的新副本。 服务器向这些客户端发送客户端重置错误。 因此,当您终止同步时,就会trigger客户端重置条件。
要测试客户端重置处理,请执行以下操作:
从客户端应用程序写入数据并等待其同步。
终止并重新启用 Device Sync。
再次运行客户端应用程序。 当应用尝试连接到服务器时,应该会出现客户端重置错误。
警告
当您在客户端应用程序中迭代进行客户端重置处理时,您可能需要反复终止并重新启用 Sync。 终止并重新启用同步会导致所有现有客户端在完成客户端重置之前无法进行同步。 为了避免在生产中出现这种情况,请在开发环境中测试客户端重置处理。