기여 목록 / 8424764
CacheStorage: Reject operations once cache closing starts
CacheStorage 캐시가 닫히기 시작한 뒤 들어온 작업을 즉시 거절하도록 변경했습니다. 닫기 전에 예약된 작업은 그대로 완료하고, 닫기 콜백이 캐시를 삭제하더라도 이후 요청의 콜백이 사라지지 않게 했습니다.
문제 설명
CacheStorageCache::Close()와 GetSizeThenClose()는 닫기 작업을 스케줄러에 배타적으로 예약합니다. 실제 백엔드가 닫히기 전까지는 backend_state_가 열려 있으므로, 이 사이에 들어온 새 요청이 닫기 작업 뒤에 예약될 수 있었습니다.
닫기 콜백에서 캐시 객체를 삭제하면 그 뒤에 대기하던 작업도 사라져 호출자가 응답 콜백을 받지 못합니다. 반대로 닫기 요청 전에 이미 예약한 작업은 백엔드가 열려 있는 동안 정상적으로 끝나야 하므로, 단순히 백엔드 상태를 미리 BACKEND_CLOSED로 바꿀 수도 없습니다.
해결 내용
cache_storage_cache.h에close_requested_와IsClosingOrClosed()를 추가했습니다.Close()와GetSizeThenClose()가 호출되면 닫기 작업을 예약하기 전에 플래그를 설정합니다. 백엔드 상태는 실제 닫기 작업이 실행될 때까지 유지합니다.Match(),MatchAll(),Keys(),Put(),BatchOperation(),WriteSideData()등 새 요청의 진입점에서 닫는 중인 캐시를 기존의 백엔드 종료 오류 경로로 거절합니다.Size()와 중복GetSizeThenClose()는 기존 종료 상태와 같이 크기 0을 반환합니다.- 할당량 조회가 비동기로 끝나는 배치·side data 경로에서도 닫기 상태를 다시 검사합니다. 조회가 시작된 뒤 캐시 닫기가 요청돼도 뒤늦게 새 작업을 예약하지 않습니다.
닫기 전에 스케줄러에 들어간 작업은 계속 실행됩니다. 새 요청만 조기에 완료시키므로 닫기 콜백에서 캐시를 삭제해도 대기 중인 새 요청의 콜백이 유실되지 않습니다.
테스트 방법
cache_storage_cache_unittest.cc에 스케줄러를 의도적으로 막아 닫기 요청과 실제 종료 사이를 재현하는 회귀 테스트를 추가했습니다. 메모리·디스크 캐시 설정에서 다음을 확인합니다.
| 테스트 | 검증 내용 |
|---|---|
OpsFailWhileCloseIsPending |
Close() 이후의 새 요청은 닫기 전에 오류 콜백을 받고, 닫기 전에 예약한 작업은 정상 완료합니다. |
OpsFailWhileGetSizeThenCloseIsPending |
GetSizeThenClose()에서도 같은 요청 차단과 기존 작업 완료를 확인합니다. |
QuotaCallbacksFailWhileCloseIsPending |
배치와 side data의 할당량 조회가 닫기 중에 완료돼도 오류 콜백을 돌려줍니다. |
패치 설명에는 집중 실행한 CacheStorageCache, CacheStorageManager, CacheStorageScheduler 테스트 344개가 통과했다고 기록돼 있습니다. 보고서 작성 과정에서 Chromium 테스트를 별도로 실행하지는 않았습니다.
배운 점
- 닫기 작업을 큐에 넣는 순간과 백엔드가 실제로 닫히는 순간은 다릅니다. 새 작업을 차단하려면 이 중간 상태를 별도로 표현해야 합니다.
- 닫기 요청 전에 예약된 작업과 이후 요청을 구분하면 기존 작업을 안전하게 마치면서 콜백 유실을 막을 수 있습니다.
- 비동기 할당량 조회처럼 요청 진입 후 다시 스케줄러에 들어가는 경로는 완료 시점에도 닫기 상태를 확인해야 합니다.