Device Syncを使用するアプリケーションを開発する際には、エラー ハンドラーを設定する必要があります。 このエラー ハンドラーは、失敗した同期関連の API 呼び出しを検出し、応答します。
同期された邦土 の作成時に、FlexibleSyncConfiguration に syncErrorHandler プロパティを追加します。syncErrorHandler
は SyncErrorHandlerコールバック関数です。 はSyncErrorHandler
SyncError をパラメーターとして受け入れます。SyncError
邦土で が発生するたびに、コールバック関数はSyncError
を引数として呼び出されます。
final config = Configuration.flexibleSync(currentUser, [Car.schema], syncErrorHandler: (SyncError error) { print("Error message${error.message}"); }); final realm = Realm(config);
syncErrorHandler
を指定しない場合のデフォルトの動作はSyncError
をコンソールに出力します。
Tip
一般的な Device Sync エラーのリストとその処理方法については、App Services Device Sync ドキュメントの「同期エラー 」を参照してください。
書込み (write) エラーの置換
Realm Flutter SDK v1.3 以降では、書込みエラーの修正に関する詳細情報を得ることができます。
void handleCompensatingWrite( CompensatingWriteError compensatingWriteError) { final writeReason = compensatingWriteError.compensatingWrites!.first; print("Error message: ${writeReason.reason}"); // ... handle compensating write error as needed. } final config = Configuration.flexibleSync(currentUser, [Car.schema], syncErrorHandler: (syncError) { if (syncError is CompensatingWriteError) { handleCompensatingWrite(syncError); } }); final realm = Realm(config);
クライアント リセット
Device Sync を使用する場合、クライアントリセットとは、Device Sync サーバーがクライアント Realm と同期できなくなった場合にクライアントアプリが実行する必要があるエラー回復タスクです。
この状態のクライアントは引き続きデータを実行してローカルに保存できますが、クライアントがリセットされるまで同期の変更セットを送信または受信することはできません。 同期機能を復元するには、クライアントが Realm をサーバーと一致する状態にリセットする必要があります。 クライアント上の同期できない Realm には、サーバーにまだ同期されていないデータが含まれている場合があります。
Realm SDK は、クライアントのリセット プロセス中にそのデータの回復または破棄を試行できます。 Realm SDK は、ほとんどのシナリオでクライアントのリセットを自動的に処理するメソッドを提供します。
クライアントGo リセットが発生する原因の詳細については、App Services ドキュメントの「 クライアントのリセット 」に してください。
クライアント リセット モード
クライアントリセットプロセスを管理するには、 邦土を構成するときに FlexibleSyncConfiguration.clientResetHandlerプロパティでクライアントリセットモードを指定できます。次のクライアントリセットモードを使用できます。
同期されていない変更モードを回復または破棄する(デフォルト): このクライアント リセット モードでは、クライアント リセット ハンドラーは最初に同期されていない変更の回復を試みます。 復元が失敗すると、このハンドラーは 同期されていない変更の破棄 モードに戻り、同期されていないすべてのローカル変更を削除します。 同期されていない変更モードの破棄に失敗した場合、ハンドラーは手動リカバリモードにフォールバックします。
同期されていない変更モードを回復: このクライアント リセット モードでは、クライアント リセット ハンドラーは最初に同期されていない変更の回復を試みます。 復元が失敗した場合、このハンドラーは手動復元モードにフォールバックします。
同期されていない変更を破棄するモード: このクライアント リセット モードは、最後の同期が成功した以降に行われたすべてのローカルの同期されていない変更を永続的に削除します。 復元が失敗した場合、このハンドラーは手動復元モードにフォールバックします。
手動リカバリモード: このクライアントリセットモードは、独自のリカバリ戦略を実装する方法を提供します。
次のセクションでは、これらのクライアント リセット モードの使用方法について説明します。
自動クライアントリセットと手動クライアントリセット
Realm SDK は、ほとんどのクライアント リセット エラーを自動的に処理するクライアント リセット モードを提供します。
自動クライアント リセット モードでは、Realm を閉じたり通知が欠落したりすることなく、ローカル Realm ファイルが同期可能な状態に復元されます。 次のクライアント リセット モードは自動クライアント リセットをサポートします。
同期されていない変更モードを回復する
同期されていない変更モードを回復または破棄する
同期されていない変更モードを破棄する
これらのモード間の違いは、バックエンドにまだ同期されていないデバイス上の変更をどのように処理するかに基づいています。 手動リカバリ モードのみでは、自動クライアントリセットは実行されません。
ほとんどのクライアントリセットシナリオを自動的に処理するには、 同期されていない変更を回復する モードを選択します。 これは、クライアントがリセットしたときに同期されていない変更を回復しようとします。
自動的に処理できない特定のクライアントリセットロジックがアプリに必要な場合は、自動クライアントリセットモードに手動クライアントリセットハンドラーを追加することをお勧めします。または追加する必要がある場合があります。
回復によるクライアントリセット
クライアントリカバリは、Device Sync を構成するとデフォルトで有効になる機能です。 クライアントリカバリが有効になっている場合、Realm はほとんどの場合、クライアントのリセットプロセスを自動的に管理します。 スキーマを変更すると、スキーマの変更がない場合、またはスキーマの変更以外の場合にクライアントは同期されていない変更を回復できます。
クライアントリカバリを使用するには、同期されていない変更を回復するか、同期されていない変更のクライアント リセット モードを回復または破棄して Realm を構成します。
クライアントリカバリが有効になっている場合、バックエンドとクライアントの両方が同じオブジェクトに変更を加えた場合に競合が解決される方法など、オブジェクトの統合方法がこれらのルールによって決まります。
クライアントがリセットされる前に同期されなかったローカルで作成されたオブジェクトが同期されます。
オブジェクトがサーバー上で削除されたが、復元されたクライアントで変更された場合は、削除が優先され、クライアントは更新を破棄します。
リカバリ クライアントでオブジェクトが削除されたが、サーバーでは削除された場合、クライアントはサーバーの削除指示を適用します。
同じフィールドへの更新が競合する場合は、クライアント更新が適用されます。
クライアントリカバリの構成の詳細については、App Services ドキュメントの「クライアントリカバリ 」を参照してください。
アプリがスキーマの重大な変更を行った場合、クライアント回復は実行できません。 重大な変更とは、処理するために追加のアクションが必要になる、サーバー側のスキーマで行うことができる変更です。 このシナリオでは、クライアント リセットは手動エラー クライアント リセット フォールバックにフォールバックします。
スキーマの重大な変更と重大でない変更の詳細については、App Services ドキュメントの「 重大な変更と重大でない変更のクイック リファレンス」を参照してください。
同期されていない変更モードの回復または破棄
同期されていない変更を回復または破棄する モードでは、クライアントのリセット中に同期されていないすべてのローカル変更を自動的に回復しようとします。 クライアントリセットモードを指定しない場合、クライアントリセット動作のデフォルトは同期されていない変更を回復または破棄します。 自動リカバリプロセスが失敗した場合は、同期されていない変更モードを破棄するようにフォールバックします。 そのプロセスが失敗すると、再度手動リセットモードにフォールバックします。
同期されていない変更モードを回復または破棄することで、最も堅牢な回復プロセスが提供されます。 ただし、アプリケーションがまだバックエンドに同期されていないローカル データを失うことができない場合は、同期されていない変更モードの回復または破棄は使用しないでください。
同期されていない変更モードのリカバリまたは破棄の使用方法をカスタマイズするには、ReactiveOrDiscardUnsyncedchangesHandlerコールバックを Configure.clientResetHandler
に渡します。ハンドラーの機能を拡張するには、次の任意のコールバックメソッドを追加します。
onBeforeReset 。クライアントリセット前に SDK が呼び出します。このコールバックを使用して、クライアントリセットが開始される前にユーザーに通知できます。
onAfterRecovery 。これは、自動リセットが正常に完了した場合にのみ、SDK によって呼び出されます。これを使用して、クライアントリセットが完了したことをユーザーに通知できます。
onAfterDiscard 。これは、自動クライアントリセットが失敗し、ローカル破棄戦略が成功した場合にのみ SDK が呼び出します。破棄戦略が失敗した場合、このコールバックは呼び出されません。
onManagerResetFallback 。SDK は自動復元と破棄戦略が失敗した場合にのみ呼び出します。 「 手動リカバリ フォールバック 」セクションで説明されているように、リセットの失敗を処理するためにこのコールバックを実装します。
次の例では、 RecoverOrDiscardUnsyncedChangesHandler
とその各コールバックの使用を示しています。
final config = Configuration.flexibleSync(currentUser, schema, clientResetHandler: RecoverOrDiscardUnsyncedChangesHandler( // All the following callbacks are optional onBeforeReset: (beforeResetRealm) { // Executed before the client reset begins. // Can be used to notify the user that a reset is going // to happen. }, onAfterRecovery: (beforeResetRealm, afterResetRealm) { // Executed if and only if the automatic recovery has succeeded. }, onAfterDiscard: (beforeResetRealm, afterResetRealm) { // Executed if the automatic recovery has failed // but the discard unsynced changes fallback has completed // successfully. }, onManualResetFallback: (clientResetError) { // Automatic reset failed. Handle the reset manually here. // Refer to the "Manual Client Reset Fallback" documentation // for more information on what you can include here. }, ));
同期されていない変更モードを回復する
「同期されていない変更を回復」モードでは、クライアントのリセット中に同期されていないすべてのローカル変更を自動的に回復しようとします。 ただし、同期されていない変更の リカバリまたは 破棄モードとは異なり、このモードは自動復元が失敗した場合に ローカル 変更の破棄にフォールバックすることはありません。 代わりに、変更を手動で回復するためにフォールバックします。
同期されていない変更モードを使用するには、RecoverUnsyncedchangesHandlerコールバックを Configure.clientResetHandler
に渡します。このハンドラーは、次のコールバックメソッドを提供します。
onBeforeReset 。クライアントリセット前に SDK が呼び出します。このコールバックを使用して、リセットが開始される前にユーザーに通知できます。
onAfterReset 。これは、自動リセットが正常に完了した場合にのみ、SDK が呼び出します。このコールバックを使用して、リセットが正常に完了したことをユーザーに通知できます。
onManagerResetFallback 。SDK は自動復元と破棄戦略が失敗した場合にのみ呼び出します。 「 手動リカバリ フォールバック 」セクションで説明されているように、リセットの失敗を処理するためにこのコールバックを実装します。
次の例では、 RecoverUnsyncedChangesHandler
とその各コールバックの使用を示しています。
final config = Configuration.flexibleSync(currentUser, schema, clientResetHandler: RecoverUnsyncedChangesHandler( // All the following callbacks are optional onBeforeReset: (beforeResetRealm) { // Executed before the client reset begins. // Can be used to notify the user that a reset is going // to happen. }, onAfterReset: (beforeResetRealm, afterResetRealm) { // Executed after the client reset is complete. // Can be used to notify the user that the reset is done. }, onManualResetFallback: (clientResetError) { // Automatic reset failed. Handle the reset manually here. // Refer to the "Manual Client Reset Fallback" documentation // for more information on what you can include here. }, ));
同期されていない変更モードを破棄する
同期されていない変更を破棄するモードでは、最後の同期が成功した以降に行われたすべてのローカルの同期されていない変更が永続的に削除されます。 このクライアント リセット モードを使用する場合、SDK は Realm を閉じることなく、通知を完全に機能させたままに、ローカル Realm ファイルを同期可能な状態に復元します。 このプロセスが失敗した場合は、手動リカバリモードにフォールバックします。
バックエンドにまだ同期されていないローカル データをアプリケーションが失うことができない場合は、同期されていない変更モードを回復または破棄しないでください。
同期されていない変更を破棄するモードを使用するには、 DishardUnsyncedchangesHandlerコールバックを Configure.clientResetHandler
に渡します。このハンドラーは、次のコールバックメソッドを提供します。
onBeforeReset 。クライアントリセット前に SDK が呼び出します。このコールバックを使用して、リセットが開始される前にユーザーに通知できます。
onAfterReset 。これは、リセットが正常に完了した場合にのみ、SDK が呼び出します。これを使用して、リセットが完了したときにユーザーに通知できます。
onManagerResetFallback 。SDK は自動復元と破棄戦略が失敗した場合にのみ呼び出します。手動リカバリ セクションで説明されているように、リセットの失敗を処理するためにこのコールバックを実装します。
次の例では、 DiscardUnsyncedChangesHandler
とその各コールバックの使用を示しています。
final config = Configuration.flexibleSync(currentUser, schema, clientResetHandler: DiscardUnsyncedChangesHandler( onBeforeReset: (beforeResetRealm) { // Executed before the client reset begins. // Can be used to notify the user that a reset is going // to happen. }, onAfterReset: (beforeResetRealm, afterResetRealm) { // Executed after the client reset is complete. // Can be used to notify the user that the reset is done. }, onManualResetFallback: (clientResetError) { // Automatic reset failed. Handle the reset manually here. // Refer to the "Manual Client Reset Fallback" documentation // for more information on what you can include here. }, ));
手動リカバリフォールバック
スキーマの重大な変更が発生した場合など、リカバリを使用したクライアントのリセットが自動的に完了しない場合、クライアントのリセットプロセスは手動のエラーハンドラーに降格します。 これは、次のいずれかの自動クライアント リセット モードで発生する可能性があります。
同期されていない変更モードを回復する
同期されていない変更モードを回復または破棄する
同期されていない変更モードを破棄する
これらのモードのクライアント リセット ハンドラーのonManualResetFallback
コールバックで、手動クライアント リセットの実装を指定する必要があります。
で、コールバックのonManualResetFallback
パラメータの ClientResetError.resetRealm()ClientResetError
メソッドを使用してクライアントリセットを開始します。ClientResetError.resetRealm()
は、デバイス上の邦土を削除し、サーバーから関連データをダウンロードすることで、クライアントリセットを実行します。このメソッドを使用する前に、リセットする邦土のすべてのインスタンスを閉じる必要があります。
次の例では、同期されていない変更をすべて破棄して、エラーが発生した場合を手動で処理する方法を示しています。
// Lazily initialize `realm` so that it can be used in the callback // before the realm has been opened. late Realm realm; final config = Configuration.flexibleSync(currentUser, schema, // This example uses the `RecoverOrDiscardUnsyncedChangesHandler`, // but the same logic could also be used with the `RecoverUnsyncedChangesHandler` // or the `DiscardUnsyncedChangesHandler`. clientResetHandler: RecoverOrDiscardUnsyncedChangesHandler( onManualResetFallback: (clientResetError) { // 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) { // You must close the Realm before attempting the client reset. realm.close(); // Attempt the client reset. try { clientResetError.resetRealm(); // Navigate the user back to the main page or reopen the // the Realm and reinitialize the current page. } catch (err) { // Reset failed. // Notify user that they'll need to update the app } } }, ));
手動リカバリモード
データ回復プロセスをカスタマイズする必要がある頻度の低いケースには、 手動リカバリ モード を使用します。 ほとんどの場合、クライアント リセットには他の戦略のいずれかを使用する必要があります。 自動リカバリ ロジックがアプリで機能せず、同期されていないローカル データを破棄できない場合は、手動のクライアント リセット ハンドラーを使用することをお勧めします。
手動リカバリモードを使用するには、 に ManualRecoveryHandlerコールバックを渡します。Configure.clientResetHandler
ハンドラーはクライアントリセットを実行できる オンマニュアルリセットコールバックを提供します。onManualReset
で、コールバックの パラメータの ClientResetError.resetRealm() ClientResetError
メソッドを使用してクライアントリセットを開始します。ClientResetError.resetRealm()
は、デバイス上の邦土を削除し、サーバーから関連データをダウンロードすることで、クライアントリセットを実行します。このメソッドを使用する前に、リセットする邦土のすべてのインスタンスを閉じる必要があります。
// Lazily initialize `realm` so that it can be used in the callback // before the realm has been opened. late Realm realm; final config = Configuration.flexibleSync(currentUser, schema, clientResetHandler: ManualRecoveryHandler((clientResetError) { // You must close the Realm before attempting the client reset. realm.close(); // Handle manual client reset here... // Then perform the client reset. clientResetError.resetRealm(); }));
クライアント リセット処理をテストします
Device Sync を終了して再度有効にすることで、アプリケーションのクライアント リセット処理を手動でテストできます。
同期を終了して再度有効にすると、以前に同期に接続したことのあるクライアントは、クライアント リセットを実行するまで接続できなくなります。 同期を終了すると、クライアントが同期できるようにするメタデータがサーバーから削除されます。 クライアントは、サーバーから Realm の新しいコピーをダウンロードする必要があります。 サーバーはこれらのクライアントにクライアント リセット エラーを送信します。 したがって、同期を終了すると、クライアントのリセット条件がtriggerされます。
クライアント リセット処理をテストするには:
クライアント アプリケーションからデータを書き込み、同期されるまで待ちます。
Device Sync を終了して再度有効にします。
クライアント アプリを再度実行します。 アプリは、サーバーに接続しようとすると、クライアント リセット エラーを取得します。
警告
クライアント アプリケーションでクライアント リセット処理を反復処理している間に、同期を繰り返し終了して再度有効にする必要がある場合があります。 同期を終了して再度有効にすると、既存のすべてのクライアントは、クライアントのリセットが完了するまで同期できなくなります。 本番環境でこれを回避するには、開発環境でクライアントのリセット処理をテストします。