Quick Reference
crash recovery는 process를 다시 띄우는 것으로 끝나지 않습니다. 어떤 match가 어느 revision까지 진행됐는지, 결과·보상이 이미 확정됐는지, stale process가 다시 input을 받지 않는지 판단해야 합니다. game mode마다 복구 방식을 하나로 고정합니다.
| mode 성격 | 우선 선택 | 필요한 기록 |
|---|---|---|
| 짧은 casual match | 무효 처리 또는 재queue | match 시작·종료 reason, 참여자 |
| 진행 상태가 중요한 match | checkpoint에서 재개 | authoritative checkpoint, input 또는 revision, owner epoch |
| 결과가 이미 확정된 match | 결과 조회·재전송 | immutable result ID, reward 처리 상태 |
client의 마지막 화면이나 마지막 packet을 server state로 복구하지 않습니다. 복구 기준은 authoritative checkpoint, durable match lifecycle record, idempotent result record입니다. 그 셋이 없으면 crash 뒤에 무엇이 실제로 일어났는지 확정할 근거가 없습니다.
crash를 감지한 뒤
health lease 만료 또는 process termination 감지
-> match directory의 owner epoch 무효화
-> 새 admission과 backfill 중지
-> mode별 recovery policy 선택
-> checkpoint restore 또는 match 종료 확정
-> client에 recovery·결과 조회 경로 통지새 owner를 열기 전에 이전 owner의 lease 또는 fencing token을 만료시킵니다. network partition으로 이전 process가 살아 있는데 control plane만 끊긴 경우가 있으므로, 단순 timeout 뒤 두 process가 같은 match를 실행하면 안 됩니다. client admission도 현재 owner epoch와 맞는 grant만 허용합니다.
checkpoint는 어느 tick 또는 state revision을 나타내는지, schema와 rule revision이 무엇인지 포함합니다. 새 server build가 checkpoint schema를 읽지 못하면 restore가 아니라 migration 또는 mode-specific 종료를 선택해야 합니다. checkpoint 주기가 길수록 crash 뒤 잃는 진행이 커지고, 너무 짧으면 persistence I/O가 simulation을 밀 수 있습니다.
결과와 보상을 한 번만 확정하기
crash 직전에 result save가 성공했지만 response를 보내지 못했을 수 있습니다. client retry나 recovery worker는 새 result를 만들지 않고 matchId + resultVersion 같은 immutable key로 기존 결과를 조회합니다. reward는 같은 result key를 unique constraint로 사용해 여러 번 적용되지 않게 합니다.
function finalizeRecovery(matchId: string, outcome: Outcome) {
const result = results.insertIfAbsent({ matchId, outcome });
grants.applyOnce({ key: `reward:${result.id}`, players: result.players });
return result;
}insertIfAbsent는 실제 database transaction 또는 unique constraint로 구현해야 합니다. process memory의 Map은 crash와 다중 recovery worker 사이에서 중복을 막지 못합니다. 이 원칙은 게임 결과와 보상과 같습니다.
자주 틀리는 부분
health check가 실패했다고 무조건 match를 즉시 패배 처리하면, 일시 dependency fault나 control plane partition을 실제 crash와 구분하지 못합니다. owner lease, process signal, checkpoint freshness, client disconnect 패턴을 함께 보고 mode 정책을 적용합니다.
반대로 crash를 client에게 숨기려고 무기한 reconnect만 시도하게 두면, 이미 사라진 session을 기다리며 UX와 queue capacity를 모두 잃습니다. recovery 가능한지, 종료됐는지, 다시 queue에 들어가야 하는지를 명확한 session state로 알려야 합니다.
참고 링크
2 sources