GeneXus で生成したスマートデバイス用オフラインアプリケーションでは、データ同期を実行すると、保留中のすべての同期イベントが処理され、一括で (つまり 1 回のリクエストで) サーバーに送信されます。
この機能には正当性があります。具体的には、主キーと外部キーが正しく処理され、サーバー側とデバイスのデータベース情報の一貫性が保証されます。たとえば、アプリケーションで次のアクションを実行するものとします。
- Customer テーブルに、CustomerId = 1 の新しいレコードを挿入する
- Invoice テーブルに、CustomerId = 1 に対する関連性 (外部キー) を持つ新しいレコードを挿入する
- Invoice テーブルに、同様に CustomerId = 1 に対する関連性 (外部キー) を持つ別のレコードを挿入する
この情報がすべてサーバーに同期されると、データの一貫性が保たれます。自動採番機能の適用に起因してサーバーの顧客レコードの CustomerId が変更された場合、該当する顧客を正しく参照するように Invoice テーブルのレコードも変更されます。さらに、同期リクエストに対する応答として、このデータ変更情報がクライアントに返され、デバイスのオフラインデータベースに適用されます。
ただし、保留中のすべての情報が一括で送信されるため、パフォーマンスの低下を伴います。アプリケーションで複数のオフラインデータベース操作を行い、その結果として多くの同期イベントが作成される場合、この同期方法ではいくつかの問題が発生し、アプリケーションのユーザーエクスペリエンスに悪影響を及ぼす可能性があります。サーバーに対する同期リクエストが非常に大きくなり、ネットワーク接続問題などが原因でリクエストが失敗すると、同じ処理を繰り返さなければならないためです。
この問題を解決するには、データベースイベントのデータを非常に大きな 1 つのリクエストとして送信するのではなく、複数の小さなリクエストに分けて送信します。重要なことは、データの一貫性が保たれるようにすることです。たとえば、前述のシナリオでは、顧客と請求書に対するアクションを複数の異なるリクエストに分けることはできません。仮に顧客を 1 つのリクエストで送信し、請求書を別のリクエストで送信したとします。この場合、サーバー側での最初のリクエストの処理時に CustomerId が変更されていたとしても、2 つ目のリクエストの処理時にはその CustomerId の変更情報を認識できず、請求書では、最初に選択された顧客レコードと一致しない CustomerId = 1 が参照されたままになります。
同期 API に SetSendCheckpoint という新しいメソッドが追加され、保留中のイベントテーブルにチェックポイントを追加できるようになりました。これらのチェックポイントはほかの同期イベント (挿入、更新、削除) と同時に挿入され、送信操作を (自動または手動で) 実行すると、保留中のイベントが日付順に処理され、チェックポイントが見つかるまでリクエストに追加されます。その時点でリクエストがサーバーに送信され、保留中の残りのイベントに対しても同様のプロセスが繰り返されます。
この方法では、サーバーに対して複数のリクエストを使用してデータ同期を実行することで、リクエストのサイズに起因するパフォーマンスやネットワークの問題を回避できます。
注: 開発者が行う必要があるのは、送信操作を 1 回実行することだけです。チャンク単位でのイベント送信メカニズムは、プラットフォームの柔軟なクライアントによって内部的に処理されます。
これは完全にアプリケーション開発者の判断によります。アプリケーションの機能と処理対象のデータに応じて、妥当なサイズの同期リクエストが作成されるように、チェックポイントをコードに追加する必要があります。
注: 主キーの自動採番を行うアプリケーションでチェックポイントを使用する際には、前述のような問題が発生する可能性があることを踏まえて慎重に対応してください。
デバイスの位置を追跡し、その情報をデバイスのデータベースに 5 分間隔で保存する必要があるものとします。同期リクエストの巨大化を防ぐために、100 件挿入したらチェックポイントを追加するものとします。この場合のコードは次のようになります。
Event 'LocationChanged'
composite
SaveCurrentLocation()
do 'SetCheckpointIfNeeded'
endcomposite
EndEvent
Sub 'SetCheckpointIfNeeded'
composite
&countStr = ClientStorage.Get('SyncEventsCount')
&count = Int(&countStr) + 1
if &count = 100
Synchronization.SetSendCheckpoint()
&count = 0
endif
&countStr = &count.ToString()
ClientStorage.Set('SyncEventsCount', &countStr)
endcomposite
EndSub
この同期方法は GeneXus 16 Upgrade 3 以降で利用できます。
|