EditingsController#index N+1 queries via fetch_cache — cache cold overlay
Fix Plan: Api::V1::EditingsController#index Latency (장기 개선)
Changes#
tesla: app/models/concerns/cachable.rb#
- What:
fetch_cache_multi메서드 추가 — 동일 모델의 여러 ID를 한 번에Rails.cache.fetch_multi로 조회하는 collection-level batch fetch. 캐시 miss인 항목만 개별find_by_id로 DB 조회 후 캐시에 저장. - Why: 현재
fetch_cache는 per-record 호출로 N+1 Redis 조회 발생.fetch_cache_multi로 25건 × 7연관 = 175회 → 모델별 1회(최대 7회)로 감소. - Lines: 58-70 이후에 새 메서드 추가
tesla: app/models/concerns/cachable.rb#
- What:
fetch_cache메서드에ActiveSupport::Notifications.instrument계측 추가 —cache.fetch_cache이벤트로 model_name, hit/miss 여부를 APM에 전달. - Why: RCA 권장사항 "APM에서 fetch_cache 호출 횟수와 miss rate를 계측하여 cold cache 상황을 모니터링"
- Lines: 58-70 (기존 메서드 wrapping)
tesla: app/serializers/editing_serializer.rb#
- What:
prefetch_caches클래스 메서드 추가 — collection 직렬화 전에 모든 연관 객체 ID를 수집하여fetch_cache_multi로 일괄 조회. 결과를 thread-local 또는 instance variable에 저장하여 이후_user,_editor등 호출 시 이미 로드된 캐시에서 즉시 반환. - Why: Serializer 아키텍처를 collection-level batch fetch로 전환하는 reference implementation.
- Lines: 8-18 전후에 추가
tesla: app/repositories/editing_repository.rb#
- What:
default_joins에서includes(:user, :editor, :escalated_by, :level, :category, :workarea, :record)eager loading 추가 — serializer에서fetch_cache호출 시 이미 메모리에 로드된 연관 객체를 활용할 수 있도록 함. 기존 raw LEFT JOIN + aliased SELECT는 레거시 호환을 위해 유지하되, AR 연관 객체도 함께 preload. - Why:
default_joins의 SELECT alias 결과와 serializer output을 일치시키는 구조로 통합. eager load된 association이 존재하면fetch_cache에서 DB fallback을 건너뛸 수 있음. - Lines: 189-212
Acceptance Criteria#
-
Cachablemodule에fetch_cache_multi(model_name, ids)public instance method가 존재 -
fetch_cache_multi가Rails.cache.fetch_multi를 사용하여 batch 조회 -
fetch_cache에ActiveSupport::Notifications.instrument('cache.fetch_cache', ...)계측이 포함 -
EditingSerializer에prefetch_caches메서드가 존재하고 collection 모드에서 호출 가능 -
editing_repository.rb의default_joins에includes또는preload가 추가 - 변경된 모든 파일이
ruby -c문법 검증 통과
Tests#
- 기존 테스트:
bundle exec srb tc(Sorbet type check on changed files) - 신규 테스트: 없음 (agent 환경에서 rspec 실행 불가)