同期セッションの管理 - React Native SDK
項目一覧
Atlas Device Sync を使用すると、React Native SDK は 同期セッション を使用して、バックグラウンドで Atlas とデータを同期します。 同期された Realm を開くたびに同期セッションが開始されます。
前提条件
同期セッションを管理する前に、次の操作を実行する必要があります。
同期された Realm に
useRealm()
フックを使用するコンポーネントを、AppProvider
、UserProvider
、RealmProvider
コンポーネントとラップします。 同期された Realm の構成と開きの詳細については、「 同期された Realm の開き方 」を参照してください。
同期セッションにアクセス
useRealm()
フックを使用して、 コンポーネント内の同期された Realm にアクセスします。 Realm の Realm.syncSessionプロパティを使用して同期セッションにアクセスします。
import React, {useEffect} from 'react'; import {Context} from '../RealmConfig'; const {useRealm} = Context; function AccessSyncSession() { const realm = useRealm(); async function workWithSyncSession() { const {syncSession} = realm; // Do stuff with sync session... } // ... }
同期セッションの一時停止または再開
同期された Realm を起動すると、同期セッションが開始されます。 Realm の同期セッションを一時停止および再開できます。 開いている Realm が複数ある場合、一時停止は他の Realm の同期セッションには影響しません。
同期を一時停止するには、 Realm.syncSession.一時停止 () 使用して複数のドキュメントを挿入できます。 同期を再開するには、 Realm.syncSession.resume() メソッドを 使用して複数のドキュメントを挿入できます。
import React, {useEffect, useState} from 'react'; import {Context} from '../RealmConfig'; const {useRealm} = Context; function ToggleSyncSession() { const realm = useRealm(); const [isPaused, setIsPaused] = useState(false); async function toggleSyncSession() { if (isPaused) { await realm.syncSession?.resume(); } else { await realm.syncSession?.pause(); } setIsPaused(!isPaused); } return ( <Button title={isPaused ? 'Pause Sync' : 'Unpause Sync'} onPress={toggleSyncSession} /> ); }
同期セッションを一時停止するタイミング
ほとんどのアプリケーションでは、同期セッションを手動で一時停止して再開する必要はありません。 ただし、同期セッションを一時停止または一時停止する必要がある状況もいくつかあります。
ユーザーが特定のアクションを実行した後にのみ同期したい場合
特定の時間のみ同期したい場合
ネットワーク接続が不十分な場合、同期は試行しないでください
同期セッションを明示的に接続するよう強制したい場合
ネットワーク接続が不十分な場合、ネットワーク接続を確立しようとすると、ユーザーのデバイスのバックアップが枯渇する可能性があります。
同期セッションを明示的に接続するよう 強制する 場合は、一時的にオフラインであることがほとんどです。 同期クライアントは接続を試み、失敗すると指数バックオフになります。 長時間オフラインになると、クライアントがすぐに再接続されないことがあります。 同期セッションを一時停止および再開すると、接続が明示的に強制されます。
同期セッションを一時停止するときは、次の点に注意してください。
クライアントがクライアントの最大オフライン時間よりも長時間オフラインになると、クライアントは同期を再開できなくなり、クライアント リセットを実行する必要があります。
同期セッションを一時停止すると、両方の方向で一時停止されます。 アプリがデバイスで行った変更はバックエンドと同期されず、バックエンドまたは他のデバイス上のデータに対する変更はデバイスに同期されません。 アップロードのみを一時停止したり、ダウンロードのみを一時停止したりする方法はありません。
クライアントがバックエンドとの同期を永続的に停止する場合は、同期セッションを一時停止しないでください。 同期を永続的に停止するには、同期された Realm の内容を同期されていない Realm にコピーし、クライアントで同期されていない Realm を使用します。
無期限の同期を停止するために、同期を一時停止しないでください。 この機能は、これらのユースケース向けに設計またはテストされていません。 この方法で使用すると、さまざまな問題が発生する可能性があります。
同期セッションのアップロードとダウンロードの進行状況を確認
同期セッションのアップロードとダウンロードの進行状況を確認するには、 Realm.syncSession.addProgressNotification() メソッドを使用して進行状況通知を追加します 使用して複数のドキュメントを挿入できます。
Realm.syncSession.addProgressNotification()
メソッドは次の 3 つのパラメータを取ります。
direction
パラメータ。 データをアップロードするための通知を登録するには、 を"upload"
に設定します。 データのダウンロードの通知を登録するには、 を"download"
に設定します。mode
パラメータ。 Realm.syncSession.removeProgressNotification()を使用してコールバックが登録解除されるまで通知が継続されるようにするには、 を"reportIndefinitely"
に設定します。 現在転送可能なバイトのみが同期されるまで通知を継続するには、 を"forCurrentlyOutstandingWork"
に設定します。transferred
とtransferable
の引数を持つコールバック関数パラメーター。transferred
はすでに転送されている現在のバイト数です。transferable
は、すでに転送された合計バイト数と転送保留中のバイト数の合計です。
注意
Flexible Sync の進行状況通知はまだ完全にはサポートされていません。 Flexible Sync を使用している場合、 は変更が統合された後にのみダウンロードを報告します。 パーティションベースの同期では、変更のダウンロードが進行状況に応じて継続的な通知が行われます。 アップロードにより、両方の同期モードにおいて進行中の進行状況通知が報告されます。
次の例では、 syncSession
にコールバックを登録して、アップロード イベントを無期限にリッスンします。 この例では、Realm に書き込み、 syncSession
通知コールバックの登録を解除します。
import React, {useEffect, useState} from 'react'; import {SyncedRealmContext} from '../RealmConfig'; const {useRealm} = SyncedRealmContext; import {Text} from 'react-native'; function CheckUploadProgress() { const realm = useRealm(); const [uploadProgressPercent, setUploadProgressPercent] = useState(0); useEffect(() => { const progressNotificationCallback = (transferred, transferable) => { // Convert decimal to percent with no decimals // (e.g. 0.6666... -> 67) const percentTransferred = parseFloat((transferred / transferable).toFixed(2)) * 100; setUploadProgressPercent(percentTransferred); }; // Listen for changes to connection state realm.syncSession?.addProgressNotification( Realm.ProgressDirection.Upload, Realm.ProgressMode.ReportIndefinitely, progressNotificationCallback, ); // Remove the connection listener when component unmounts return () => realm.syncSession?.removeProgressNotification( progressNotificationCallback, ); // Run useEffect only when component mounts }, []); return <Text>Percent Uploaded: {uploadProgressPercent} %</Text>; }
import React, {useEffect, useState} from 'react'; import {Context} from '../RealmConfig'; const {useRealm} = Context; import {Text} from 'react-native'; function CheckUploadProgress() { const realm = useRealm(); const [uploadProgressPercent, setUploadProgressPercent] = useState(0); useEffect(() => { const progressNotificationCallback: Realm.ProgressNotificationCallback = ( transferred, transferable, ) => { // Convert decimal to percent with no decimals // (e.g. 0.6666... -> 67) const percentTransferred = parseFloat((transferred / transferable).toFixed(2)) * 100; setUploadProgressPercent(percentTransferred); }; // Listen for changes to connection state realm.syncSession?.addProgressNotification( Realm.ProgressDirection.Upload, Realm.ProgressMode.ReportIndefinitely, progressNotificationCallback, ); // Remove the connection listener when component unmounts return () => realm.syncSession?.removeProgressNotification( progressNotificationCallback, ); // Run useEffect only when component mounts }, []); return <Text>Percent Uploaded: {uploadProgressPercent} %</Text>; }
ネットワーク接続の確認
Realm のオフラインファーストの設計により、接続が利用可能になるとバックグラウンドでデータが同期されるため、通常、現在のネットワーク接続状態を確認する必要はありません。 つまり、Realm SDK には、サーバーへのネットワーク接続の現在の状態を取得するためのメソッドが用意されています。
サーバーへの接続の現在の状態を確認するには、 Realm.syncSession.isConnected()を呼び出します。 このメソッドは、ネットワーク接続があり、同期セッションがアクティブな場合、 true
であるブール値を返します。
接続状態の変更をリッスンするには、 Realm.syncSession.addConnectionNotification()を呼び出します コールバック関数を渡して、ネットワークの変更を引数として処理します。 リスナーの登録を解除するには、同じコールバック関数をRealm.syncSession.removeConnectionNotification() に渡します。
import React, {useState, useEffect} from 'react'; import {SyncedRealmContext} from '../RealmConfig'; const {useRealm} = SyncedRealmContext; import {Text} from 'react-native'; function CheckNetworkConnection() { const realm = useRealm(); const [isConnected, setIsConnected] = useState( realm.syncSession?.isConnected(), ); useEffect(() => { const connectionNotificationCallback = (newState, oldState) => { console.log('Current connection state: ' + newState); console.log('Previous connection state: ' + oldState); setIsConnected(realm.syncSession?.isConnected()); }; // Listen for changes to connection state realm.syncSession?.addConnectionNotification( connectionNotificationCallback, ); // Remove the connection listener when component unmounts return () => realm.syncSession?.removeConnectionNotification( connectionNotificationCallback, ); // Run useEffect only when component mounts }, []); return ( <Text> {isConnected ? 'Connected to Network' : 'Disconnected from Network'} </Text> ); }
import React, {useState, useEffect} from 'react'; import {Context} from '../RealmConfig'; const {useRealm} = Context; import {Text} from 'react-native'; function CheckNetworkConnection() { const realm = useRealm(); const [isConnected, setIsConnected] = useState( realm.syncSession?.isConnected(), ); useEffect(() => { const connectionNotificationCallback: Realm.ConnectionNotificationCallback = (newState, oldState) => { console.log('Current connection state: ' + newState); console.log('Previous connection state: ' + oldState); setIsConnected(realm.syncSession?.isConnected()); }; // Listen for changes to connection state realm.syncSession?.addConnectionNotification( connectionNotificationCallback, ); // Remove the connection listener when component unmounts return () => realm.syncSession?.removeConnectionNotification( connectionNotificationCallback, ); // Run useEffect only when component mounts }, []); return ( <Text> {isConnected ? 'Connected to Network' : 'Disconnected from Network'} </Text> ); }
複数の同期セッション
セッションマルチ プレフィックスを有効にする を使用して、 Realmアプリの複数の同期セッションを統合します。ファイル記述子の制限に達するというエラーが表示され、かつ多数の同期セッションを使用していることがわかっている場合にのみ、セッションマルチプレフィックスを使用してください。
セッションのマルチプレフィックスを有効にするには、 Realm.App.Sync.enableSession Multilessing()を呼び出します Realm.Appで起動する
import React, {useEffect} from 'react'; import {Context} from '../RealmConfig'; import {AppProvider, UserProvider, useUser, useApp, Realm} from '@realm/react'; function AppWrapper() { return ( <AppProvider id={APP_ID}> <UserProvider fallback={<LogIn />}> <RealmWrapper> <RestOfApp /> </RealmWrapper> </UserProvider> </AppProvider> ); } type RealmWrapperProps = { children: React.ReactNode; }; function RealmWrapper({children}: RealmWrapperProps) { const app = useApp(); Realm.App.Sync.enableSessionMultiplexing(app); return <RealmProvider sync={{flexible: true}}>{children}</RealmProvider>; }