Skip to content

Persist + sync review logs (streak foundation)#15

Merged
bootuz merged 9 commits into
mainfrom
feature/review-log-sync
Jun 5, 2026
Merged

Persist + sync review logs (streak foundation)#15
bootuz merged 9 commits into
mainfrom
feature/review-log-sync

Conversation

@bootuz
Copy link
Copy Markdown
Owner

@bootuz bootuz commented Jun 5, 2026

Summary

Sub-project 1 of 2 for the streak system. Persists every FSRS review as an immutable ReviewLog and syncs them to Firestore — fixing the gap where StudyViewModel.onRate computed ScheduleResult.log and discarded it. This gives the app a real per-review history (the data the streak — and later stats/heatmap — will derive from) plus a synced backup.

  • Room: new immutable review_logs table + ReviewLogDao, AzriDatabase → v2 with an additive Migration(1,2) (CREATE TABLE matched byte-for-byte to Room's generated schema — verified against AzriDatabase_Impl.kt; no destructive wipe).
  • Domain/repo: ReviewLog/ReviewLogDto gain id/cardId (defaulted — SchedulingService.schedule() stays pure); ReviewLogRepository.append() assigns a UUID + marks the row dirty.
  • Write path: onRate now persists result.log (best-effort, fire-and-forget — never blocks rating).
  • Sync: flat users/{uid}/reviewLogs/{logId} (each carrying cardId), append-only union — push dirty logs then clear; pull inserts only ids not already local (@Insert(OnConflictStrategy.IGNORE)), no last-write-wins since logs are immutable. The existing card/deck/folder sync is untouched.

Out of scope (sub-project 2): the streak itself (will consume ReviewLogRepository.observeLogs()); the iOS cards/{id}/history subcollection; log pruning; backfilling history for already-rated cards.

Test plan

  • ReviewLogDtoTest, ReviewLogMapperTest (incl. null state/due) — id/cardId/all fields round-trip domain ↔ entity ↔ DTO.
  • ReviewLogRepositoryTestappend assigns the injected id + cardId + dirty.
  • StudyViewModelTest — rating appends exactly one log with the right cardId/rating.
  • SyncManagerTest — dirty logs pushed then cleared; pull unions remote logs and SyncManager's own filter skips an already-present id (asserted via inserted-batch capture, not just DAO dedup).
  • Full unit-test suite green; instrumented sources compile; :app:assembleDebug BUILD SUCCESSFUL.
  • Manual smoke (pending emulator — verifies the live Room migration): install over an existing v1 build (no uninstall) → opens without a schema crash, data preserved; rate cards → review_logs fills; signed-in sync → users/{uid}/reviewLogs populates and a repeat sync adds no duplicates.

🤖 Generated with Claude Code

@bootuz bootuz merged commit 29c2b95 into main Jun 5, 2026
1 check passed
@bootuz bootuz mentioned this pull request Jun 5, 2026
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant