AppSheet アプリでは、複数のユーザーが同時にデータを追加、更新、削除できます。このことから、おのずと「複数のユーザーが同時に同じデータを更新するのをどうやって処理するのか」という疑問が出てきます。
ルールは簡単です。最後に書き込んだユーザーの内容が残ります。
- あるユーザーがモバイル デバイスでレコードを追加、更新、削除すると、そのユーザーが行った変更がクライアント デバイスまたはブラウザでキューに入ります。クライアントが変更を同期すると、クライアントが追加、更新、または削除のリクエストをサーバーに送信します。
- サーバーは、クライアントの同期により送信された追加、更新、または削除のリクエストを受信すると、そのリクエストを実行します。クライアントから複数のリクエストが同時またはほぼ同時に同じテーブルに到着した場合、サーバーは通常、クライアントからのリクエストを順番に並べ、リクエストを 1 つずつ実行します。このため、クライアントからの 2 番目のリクエストは、クライアントからの最初のリクエストの実行が完了した後でなければ実行されません。
- 変更の単位は 1 行です。多くのアプリケーションは、2 つのクライアントが同時に同じ行を更新することのないよう動作します。たとえば、1 つのクライアントがある顧客のレコードを更新している間に、2 番目のクライアントが別の顧客のレコードを更新することもあります。これら 2 つの同時更新が競合することはありません。
- 2 つのクライアントがたまたまほぼ同時に同じ行を変更した場合、後のクライアントの変更が残ります。これは、「最後に書き込んだ内容を残す」競合回避策と呼ばれます。
- ユーザーが(アプリ経由ではなく)スプレッドシートで直接データを更新した場合も、これは、他のデータ更新として処理されます。
クライアント同期中に「最後に書き込んだ内容を残す」競合回避策を採用できるケースは 3 つあります。
追加時の UpdateExistingRecord
キーが同じ行がすでに存在する場合にユーザーが行を追加すると、その行は、2 番目のクライアントの追加リクエストに含まれるデータで更新されます。これが発生すると、2 番目の追加処理の Audit History レコードに UpdateExistingRecord プロパティが追加されます。
このプロパティには、更新された既存レコードのキーが含まれます。
これは、1 つのクライアントが同じ追加リクエストを複数回送信した場合に発生することがあります。たとえば、クライアントが追加リクエストを送信した後で、サーバーが元の追加リクエストに応答する前にネットワーク接続が切断されることがあります。この状況では、サーバーによって追加リクエストが受信され、処理されたかがクライアントにはわかりません。この場合は、後にネットワーク接続が復旧してから、クライアントが追加リクエストを再送信します。
サーバーは、クライアントの重複リクエストを検出し、それに適切に対応しようと試みます。サーバーは、各クライアントからの最近のリクエストを最長 24 時間記憶します。クライアントが同じリクエストを再度送信すると、サーバーは、重複リクエストを検出し、元のリクエストに対して返したのと同じ応答により対応します。サーバーは、各クライアントの最近のリクエストと応答を記憶することで、クライアントの重複リクエストを適切に処理しようと試みます。これにより、クライアントの追加リクエストを 2 度実行せずに済みます。
クライアントが 24 時間以上ネットワークに接続できない場合、サーバーは、元のクライアント要求を記憶できなくなります。その後クライアントが追加リクエストを再送信すると、サーバーは 2 回目の追加リクエストの実行を試みます。サーバーは、追加リクエストを実行し、レコードがすでに存在することを確認すると、2 回目の追加リクエストの Audit History に UpdateExistingRecord プロパティを追加します。UpdateExistingRecord プロパティには、元のレコードのキーが含まれます。
追加処理によってトリガーされる自動化ワークフロー ルールがアプリケーションに適用されている場合、クライアントからの最初の追加リクエストから 24 時間以上経過してからクライアントからの 2 番目の追加リクエストが送信されると、これらのルールが再度トリガーされます。
これがいつ発生したかは、2 番目の追加リクエストの Audit History の Stop レコードで確認できます。このレコードに UpdateExistingRecord プロパティが含まれている場合、最初の追加リクエストから 2 番目の追加リクエストまで 24 時間以上空く形で、追加リクエストがクライアントによって 2 回送信されています。また、クライアントからの両方の追加リクエストの追加 start Audit History レコードに同じ clientId と requestId のプロパティ値が含まれていることもわかります。
削除時の DeleteDeletedRecord
ユーザーがある行を削除したものの、そのキーを持つ行が存在しない場合、その変更は無視されます。この場合、削除処理の Audit History レコードには、すでに削除されたレコードのキーを含む DeleteDeletedRecord プロパティが追加されます。
更新時の UpdateDeletedRecord
ユーザーが行を編集したものの、そのキーを持つ行が存在しない場合、他のユーザーが先に明示的にその行を削除したことが明らかであるため、その変更は無視されます。この場合、編集処理の Audit History レコードには、削除済みレコードのキーを含む UpdateDeletedRecord プロパティが追加されます。