우선순위/심각도
드물지만 치명적인 문제입니다. 일시적인 데이터베이스 오류 발생 후 최대 30분 동안 사이트가 사용 불가능한 상태가 됩니다. 클라이언트 설정 누락으로 인한 JavaScript 오류로 인해 페이지가 제대로 로드되지 않습니다.
플랫폼
- 영향 범위: 모든 Discourse 설치 환경
- 확인된 환경: 일시적인 데이터베이스 연결 문제를 겪는 프로덕션 환경
설명
실제 결과
일시적인 데이터베이스 오류(연결 타임아웃, 풀 고갈, 네트워크 장애)가 발생하면 오류가 30분 동안 캐시됩니다. 이 기간 동안:
- 사이트가 제대로 로드되지 않습니다 - 페이지가 깨지거나 작동하지 않는 상태로 표시됩니다.
- 누락되거나 잘못된 설정으로 인해 클라이언트 측 JavaScript 오류가 발생합니다.
- 모든 요청에서 “Nil client_settings_json from the cache for ‘client_settings_json_[git_version]’” 로그가 기록됩니다.
- 브라우저에 빈 클라이언트 설정이 반환됩니다.
- 데이터베이스가 완전히 복구된 후에도 이 상태가 지속됩니다.
기대되는 결과
일시적인 데이터베이스 오류가 발생하면 시스템은 오류를 캐시하지 않아야 합니다. 데이터베이스가 복구되면 다음 요청에서 클라이언트 설정을 성공적으로 가져와 캐시하고, 사이트가 즉시 정상적인 운영으로 복귀해야 합니다.
재현 단계
- 클라이언트 설정이 구성된 Discourse 인스턴스를 시작합니다.
- 데이터베이스 연결 문제를 시뮬레이션합니다(예: 연결 풀 고갈, 네트워크 지연 도입, 또는 포트 5432 일시적 차단).
- SiteSetting.client_settings_json을 트리거하는 요청을 수행합니다(어떤 페이지 로드든 이 동작을 수행합니다).
- 오류 관찰: “Error while generating client_settings_json_uncached: [database error]”
- 페이지가 올바르게 렌더링되지 않고, JavaScript 콘솔에 설정 누락과 관련된 오류가 표시됩니다.
- 데이터베이스 연결을 복구합니다.
- 다음 30분 동안 추가 요청을 수행합니다. 데이터베이스가 정상임에도 불구하고 “Nil client_settings_json from the cache” 오류가 계속 표시됩니다.
- 30분 후, 캐시가 만료되고 사이트가 마침내 복구됩니다.
사용자 영향
이 기간 동안 사이트는 사실상 다운된 상태입니다:
- 페이지가 올바르게 렌더링되지 않습니다.
- 설정 누락으로 인해 JavaScript 애플리케이션 초기화가 실패합니다.
이것은 1초간의 데이터베이스 일시 장애를 30분간의 중단으로 전환시킵니다.
근본 원인
lib/site_setting_extension.rb 파일에서 client_settings_json_uncached 메서드가 예외를 잡아 nil을 반환합니다. 이 nil 값이 30분 동안 캐시되어 사이트를 깨뜨립니다.
제안된 수정안
이 문제를 수정하기 위한 풀 리퀘스트가 제출되었습니다. 수정안은 nil을 반환하는 대신 예외를 다시 발생시키는(re-raise) 간단한 변경이 필요합니다.
이 방식이 작동하는 이유:
- 예외를 다시 발생시키면 Discourse.cache.fetch가 오류를 캐시하는 것을 방지합니다.
- 외부의 client_settings_json 메서드에는 캐시하지 않고 “”(빈 문자열)을 반환하는 적절한 예외 처리가 이미 존재합니다.
- 데이터베이스 문제 발생 중에도 사이트가 계속 기능할 수 있습니다(다만 성능이 저하될 수 있음).
- 데이터베이스가 정상 상태가 되면 다음 요청 시 사이트가 자동으로 복구됩니다.
- 이 수정안은 일시적인 데이터베이스 오류가 30분간의 중단을 유발하는 것을 방지합니다.
영향
이 버그는 일시적인 데이터베이스 문제를 겪는 모든 Discourse 설치 환경에 영향을 미칩니다:
- 트래픽 급증 시 연결 풀 고갈
- 애플리케이션과 데이터베이스 간의 네트워크 장애
- 데이터베이스 페일오버 시나리오(예: 프라이머리/리플리카 전환)
- site_settings 테이블의 잠금 경쟁(lock contention)
- 느린 쿼리로 인한 쿼리 타임아웃
심각도: 이러한 일반적인 일시적 문제 중 어느 것이라도 근본적인 문제가 몇 초 만에 해결되더라도 전체 사이트가 30분 동안 사용 불가능하게 만듭니다.
우회 방법
지금 이 문제를 겪고 있다면, 수동으로 캐시를 지워 서비스를 복구할 수 있습니다:
Rails 콘솔에서
Discourse.cache.delete(SiteSettingExtension.client_settings_cache_key)