어떤 기능인가요?
전송 대기 상태의 타이머를 서버로 올리는 워커를 추가합니다. 앱이 종료되거나 기기가 재부팅돼도 연결 조건이 충족되면 실행됩니다.
지금 서버로 올리는 경로가 아예 없습니다. ApiService.postSimpleTimer, patchSimpleTimer, deleteSimpleTimer는 선언만 있고 프로덕션 호출부가 0이며 TimerRepositoryImpl은 로컬만 씁니다. TimerLocalDataSource.getPendingSimpleTimers()도 테스트만 소비합니다. 그래서 오프라인에서 만든 타이머가 로컬에만 쌓이고, 서버 목록 반영이 serverId = null 행을 건드리지 않으므로 개수가 단조 증가합니다. 사용자 기기에서 심플 타이머가 6개를 넘어 화면이 겹친 원인입니다.
FcmTokenSyncWorker와 FcmTokenSyncScheduler 패턴을 그대로 씁니다. Hilt Worker 배선(Configuration.Provider, HiltWorkerFactory)은 이미 있습니다
- 연결 상태 제약과 지수 백오프, 유니크 작업으로 예약해 같은 작업이 동시에 두 번 돌지 않게 합니다
- 재시도 판단은 안드로이드 의존성이 없는 정책 오브젝트로 분리해 단위 테스트로 검증합니다.
FcmTokenSyncPolicy와 같은 방식입니다
- 작업 입력에
memberId를 넣고 각 네트워크 호출 전 현재 세션과 일치하는지 확인합니다. 다르면 아무것도 보내지 않고 성공으로 종료합니다
처리 순서를 생성 → 수정 → 삭제로 고정합니다. 삭제를 먼저 처리하면 서버 개수가 일시적으로 비정상이 되는 창이 생깁니다. ExerciseSyncWorker 설계도 같은 이유로 순서를 고정했습니다.
삭제가 판정에서 이깁니다. 이미 삭제된 타이머에 수정을 보내면 서버가 "삭제됨"을 응답합니다. 그때는 로컬 행을 지웁니다. 오프라인에서 한 수정은 버립니다. 이 규칙 덕분에 조회 응답에 삭제 기록이 없어도 기기 간에 수렴합니다.
개수 상한은 서버가 수용 후 보정합니다. 상한 초과 생성 요청도 서버가 받고 편집 시각 최신순으로 상한만큼만 남깁니다. 워커는 거부를 받지 않으므로 개수 때문에 실패하는 경로가 없습니다. 밀려난 행은 다음 목록 조회에서 로컬에서도 사라집니다.
서버 작업(api-server #574, #575)이 prod에 배포된 뒤에 머지합니다. 그 전에 열면 중복 생성과 덮어쓰기가 실제로 일어납니다. #602(강제 로그아웃 시 대기 행 보존)가 선행입니다. 대기 행을 남기기로 했으므로 워커는 재로그인 후 이어서 전송해야 합니다.
작업 상세 내용
참고할만한 자료(선택)
오프라인 기능 지원 설계 문서의 구성 요소 3(TimerSyncWorker), 설계 규칙 D7(모든 쓰기 요청에 요청 식별자), D8(전송은 Worker가 맡음), 위험 요소 2(응답 유실 시 중복 생성)와 4(성공 후 응답 유실 재시도가 409로 오판)가 기준입니다.
선행 이슈는 #586(저장층, 머지), #587(읽기·쓰기 배선), #602(강제 로그아웃 시 대기 행 보존)입니다. api-server #574와 #575의 prod 배포가 머지 조건입니다.
RoomSessionDataCleaner.clearAll()이 database.clearAllTables()를 부르므로 #586에서 추가한 타이머 테이블은 세션 정리에 이미 포함됩니다. 이 이슈에서 추가할 것은 워커 취소입니다.
어떤 기능인가요?
전송 대기 상태의 타이머를 서버로 올리는 워커를 추가합니다. 앱이 종료되거나 기기가 재부팅돼도 연결 조건이 충족되면 실행됩니다.
지금 서버로 올리는 경로가 아예 없습니다.
ApiService.postSimpleTimer,patchSimpleTimer,deleteSimpleTimer는 선언만 있고 프로덕션 호출부가 0이며TimerRepositoryImpl은 로컬만 씁니다.TimerLocalDataSource.getPendingSimpleTimers()도 테스트만 소비합니다. 그래서 오프라인에서 만든 타이머가 로컬에만 쌓이고, 서버 목록 반영이serverId = null행을 건드리지 않으므로 개수가 단조 증가합니다. 사용자 기기에서 심플 타이머가 6개를 넘어 화면이 겹친 원인입니다.FcmTokenSyncWorker와FcmTokenSyncScheduler패턴을 그대로 씁니다. Hilt Worker 배선(Configuration.Provider,HiltWorkerFactory)은 이미 있습니다FcmTokenSyncPolicy와 같은 방식입니다memberId를 넣고 각 네트워크 호출 전 현재 세션과 일치하는지 확인합니다. 다르면 아무것도 보내지 않고 성공으로 종료합니다처리 순서를 생성 → 수정 → 삭제로 고정합니다. 삭제를 먼저 처리하면 서버 개수가 일시적으로 비정상이 되는 창이 생깁니다.
ExerciseSyncWorker설계도 같은 이유로 순서를 고정했습니다.삭제가 판정에서 이깁니다. 이미 삭제된 타이머에 수정을 보내면 서버가 "삭제됨"을 응답합니다. 그때는 로컬 행을 지웁니다. 오프라인에서 한 수정은 버립니다. 이 규칙 덕분에 조회 응답에 삭제 기록이 없어도 기기 간에 수렴합니다.
개수 상한은 서버가 수용 후 보정합니다. 상한 초과 생성 요청도 서버가 받고 편집 시각 최신순으로 상한만큼만 남깁니다. 워커는 거부를 받지 않으므로 개수 때문에 실패하는 경로가 없습니다. 밀려난 행은 다음 목록 조회에서 로컬에서도 사라집니다.
서버 작업(api-server #574, #575)이 prod에 배포된 뒤에 머지합니다. 그 전에 열면 중복 생성과 덮어쓰기가 실제로 일어납니다. #602(강제 로그아웃 시 대기 행 보존)가 선행입니다. 대기 행을 남기기로 했으므로 워커는 재로그인 후 이어서 전송해야 합니다.
작업 상세 내용
memberId를 넣고 호출 전 현재 세션과 일치 확인. 다르면 전송 없이 성공 종료serverId기록 후 동기화 완료 전이createRequestId사용editId와editedAt사용inFlightEditId등). #586에서 이 이슈로 미뤘습니다ClearSessionUseCase에 예약 취소 연결.FcmTokenSyncScheduler패턴lastSyncError기록TimerDao.countSimpleTimers와TimerLocalDataSource.countSimpleTimers는 호출부가 없습니다참고할만한 자료(선택)
오프라인 기능 지원 설계 문서의 구성 요소 3(TimerSyncWorker), 설계 규칙 D7(모든 쓰기 요청에 요청 식별자), D8(전송은 Worker가 맡음), 위험 요소 2(응답 유실 시 중복 생성)와 4(성공 후 응답 유실 재시도가 409로 오판)가 기준입니다.
선행 이슈는 #586(저장층, 머지), #587(읽기·쓰기 배선), #602(강제 로그아웃 시 대기 행 보존)입니다. api-server #574와 #575의 prod 배포가 머지 조건입니다.
RoomSessionDataCleaner.clearAll()이database.clearAllTables()를 부르므로 #586에서 추가한 타이머 테이블은 세션 정리에 이미 포함됩니다. 이 이슈에서 추가할 것은 워커 취소입니다.