hashira
hashira copied to clipboard
Cloud との同期をもう少しいい感じにする
現在
- upload ... local の状態を cloud にそのまま反映する
- download ... cloud の状態を local にマージする
という処理を行っている。これの問題点は、
- 環境 A と環境 B で異なる変更を行った上で各々が upload を実施した場合、どちらかの変更が失われる
- 先に download してから upload するという案もあるが、その場合手元で行った変更が失われる場合がある
なので、なるべく
- 手元の変更を失わずに、
- よそで発生した変更も失わないように local に反映する
というようにしたい。
以下の手順で同期する
- local から cloud に upload する
- cloud は upload されたデータとすでに保存されているデータをマージする (upload されてきたものの状態を優先する)
- isDeleted フラグがついているものは削除する (物理削除)
- upload 完了後、local は cloud からデータをダウンロードする
- local のデータにマージする (download したものの状態を優先する)
- isDeleted フラグがついているものは削除する (物理削除)
留意する点
- 物理削除について
- cloud だけにデータが残ってしまう可能性はないか?
- local ではすでに消えたデータが、cloud 上ではまだ残っているという状態になる可能性がある
- ただ、このケースは download 時に復活して見えるはずなので、ふたたび消すというオペレーションをすることでいつかデータの整合性が取れるはず
- 物理削除する必要があるか?
- 延々とデータが増え続けてしまうと同期にどんどん時間がかかるようになってしまうので、なるべく残しておきたくない
- cloud だけにデータが残ってしまう可能性はないか?
- upload & download について
- いつ実行する?
- 理想的には、todo に変化が発生したタイミングで常に実行する
- ネットワークが不通になる状況を考慮する必要があるので、ポーリングする必要もありそう
- isDirty フラグを使うと、一応不要な通信は抑えられるかもしれない
- いつ実行する?
- 常に upload を先にやる必要がありそう
- download を先にやると、手元の変更が失われる場合があるため
- どっかの環境とコンフリクトするような場合はまあまあやむなし
upload の戦略
-
isDirty
がついているもののみを upload の対象にする- よそで発生した変更を無駄に上書きするのを避けるため
- 帯域を温存する
- 一度も sync したことのない場合、全部の task が
isDirty: false
だが upload が済んでいないという状態になる- 初回限定で、一回全部の task を upload する必要がある
- 一度やってしまえばあとは Dirty フラグのついたものだけ upload する & 全部 download して local に反映する、というロジックでまあまあ整合性が保たれるはず
- 専用コマンドを用意しとこう
いったん実装できたが、以下の問題があることがわかった。
[問題の動作]
- タスクの追加や並びの変更があったときに、Dirty フラグのついたタスクのアップロードと、全件ダウンロードを行っている
[何が問題か]
- 手元で素早く複数回タスクを動かすと、アップロードを開始してダウンロードが済む前にいくらか Dirty なタスクが発生することになる
- アップロードとダウンロードの間で動かしたタスクは、ダウンロードによって状態が上書きされてしまうことがある
[解決案]
- タスクを動かしたときにただちにダウンロードまでやるのを止める
- Dirty 発生時はアップロードだけやっとく
- ほとぼりが冷めた頃合いを見計らってダウンロードを行う (最後にタスクを動かしてから数分後、みたいな)
- Dirty なタスクはダウンロード時に上書きしない
- これのほうが安全かも
- こっちで実装してみる
結局以下を両方実装した。
- ほとぼりが冷めた頃合いを見計らってアップロード/ダウンロードを行う
- Dirty なタスクはダウンロード時に上書きしない
なんとなくちゃんと動くようになったような気がする
ポーリングの機能は実装しなかったのだが、
- よそで変更する
- ほっといたら自分のところに同期されている
みたいなのは出来てもよさそうなので、やっぱり定期的にポーリングして UI に反映するのはやったほうが体験がよさそうかもしれない。
ダウンロードが完了したら UI をちゃんとリフレッシュするのができてない気がするのでそれは直そう。
削除したタスクに関しては同期がとれない (消えてなくなるので、元からなかったのか消したのかの判別ができない)。 これはもう諦める。