35장. Offline DB와 Queue를 transaction으로 묶는다
localStorage는 구조·transaction·용량·민감 데이터 요구를 만족하지 못한다. 검토된 SQLite 계층을 사용하고 schema version과 migration을 관리한다. Inspection, Answer, Asset, SyncCommand, Receipt를 분리한다. local id와 server id를 혼동하지 않고 mapping을 둔다. token은 DB가 아니라 Keychain/Keystore 기반 storage에 둔다.
사용자가 답을 저장하면 Answer 변경과 SyncCommand insert를 하나의 local transaction으로 commit한다. process가 직후 죽어도 명령이 남는다. queue worker는 network 표시보다 실제 endpoint 요청으로 connectivity를 판단하고 exponential backoff, jitter, deadline을 쓴다. 4xx validation은 무한 retry하지 않고 사용자 수정 상태로 보낸다.
begin;
update answer set value = ?, version = version + 1 where local_id = ?;
insert into sync_command(id, kind, entity_id, state, attempts)
values (?, 'UPSERT_ANSWER', ?, 'PENDING', 0);
commit;
DB migration 전에는 backup 가능성과 rollback을 본다. 앱 삭제·기기 교체·backup restore에서 어떤 데이터가 남고 server와 어떻게 재동기화되는지 명시한다.