Missing trashed filter in facility refresh query
RCA: Failed to refresh average cadence on bfbc2l: Calculating average cadence is not supported for trashed facility
Error Log#
Failed to refresh average cadence on bfbc2l: Calculating average cadence is not supported for trashed facility: bfbc2l
Impact#
- Service:
cupixworks-worker - 발생 횟수: 1
- 최초 발생: 2026-04-10T00:30:46.439Z
- 최근 발생: 2026-04-10T00:30:46.439Z
Root Cause Summary#
Cupix::Cron::Facility.refresh_average_cadence_on_record_created 크론 잡이 최근 24시간 내 Record가 생성된 facility를 조회할 때 trashed 상태의 facility를 필터링하지 않습니다. 이로 인해 facility bfbc2l이 trashed 상태임에도 refresh_average_cadence! 메서드가 호출되어, 해당 메서드의 trashed facility guard가 Cupix::Errors::Entity 예외를 발생시킵니다. 에러 자체는 rescue로 잡혀 로그에 기록되며 다른 facility의 처리를 중단하지는 않지만, 불필요한 에러 로그를 생성합니다.
Technical Analysis#
Code Path#
- Entry point:
config/schedule.rb:152— 매일 00:30 UTC에 cron이refresh_average_cadence_on_record_created를 실행
# config/schedule.rb:151-153
every '30 0 * * *' do
runner 'Cupix::Cron::Facility.refresh_average_cadence_on_record_created'
end
- Step 1:
lib/cupix/cron/facility.rb:14-24— 최근 1일 내 Record가 생성된 facility를 조회하되, trashed 상태를 필터링하지 않음
# lib/cupix/cron/facility.rb:14-24
def refresh_average_cadence_on_record_created
facilities = ::Facility.where(id: ::Record.where('created_at > ?', 1.day.ago).pluck(:facility_id))
Cupix::Logger.info("Refreshing average cadence on #{facilities.count} facilities by record creation")
facilities.each do |facility|
facility.refresh_average_cadence!
rescue StandardError => e
Cupix::Logger.error("Failed to refresh average cadence on #{facility.key}: #{e.message}")
end
end
- Failure point:
app/models/concerns/analysis/facility.rb:10-15—refresh_average_cadence!가 trashed facility에 대해 예외를 발생시킴
# app/models/concerns/analysis/facility.rb:9-15
def refresh_average_cadence!
if trashed?
raise Cupix::Errors::Entity.new(
code: 'ENT10000',
reason: "Calculating average cadence is not supported for trashed facility: #{key}"
)
end
# ...
end
기대 동작: trashed facility는 cadence 갱신 대상에서 제외되어야 합니다. Analysis::Facility concern의 scope인 refresh_cadence_candidates(line 6)는 이미 untrashed 필터를 포함하고 있으나, cron 메서드는 이 scope를 사용하지 않습니다.
# app/models/concerns/analysis/facility.rb:6
scope :refresh_cadence_candidates, -> { untrashed.where('next_cadence_check_at <= ?', DateTime.now).where(delay_status: false) }
실제 동작: ::Facility.where(id: ...) 쿼리가 trashed 포함 모든 facility를 반환하여, trashed facility bfbc2l에서 예외가 발생합니다.
동일한 문제가 refresh_average_cadence_on_schedule (line 26-36)에도 존재합니다. 해당 메서드도 동일한 패턴으로 trashed facility를 필터링하지 않습니다.
Log Evidence#
1. Facility trash 요청 (원인):
service:cupixworks-api "bfbc2l" "trash"
Time: 2026-04-09T00:00:00Z to 2026-04-10T01:00:00Z
{
"timestamp": "2026-04-09T05:41:21.255Z",
"service": "cupixworks-api",
"status": "info",
"message": "[204] PUT /api/v1/facilities/bfbc2l/trash (Api::V1::FacilitiesController#trash)",
"user": "jhangwon.yoon@cupix.io (user_id: 42295)",
"team": "qatest3 (id: 1131)"
}
Facility bfbc2l은 에러 발생 약 19시간 전에 trash 처리되었습니다.
2. 크론 배치 실행 로그:
service:cupixworks-worker "Refreshing average cadence"
Time: 2026-04-09T23:30:00Z to 2026-04-10T01:00:00Z
{
"timestamp": "2026-04-10T00:30:30.406Z",
"status": "info",
"message": "Refreshing average cadence on 152 facilities by record creation",
"host": "ip-10-1-18-233.us-west-2.compute.internal",
"pid": 1104873
}
동일 PID(1104873)에서 152개 facility 배치 처리가 시작되었고, 16초 후 bfbc2l에서 에러가 발생했습니다.
3. 에러 로그:
service:cupixworks-worker "bfbc2l"
Time: 2026-04-09T23:30:00Z to 2026-04-10T01:00:00Z
{
"timestamp": "2026-04-10T00:30:46.439Z",
"status": "error",
"message": "Failed to refresh average cadence on bfbc2l: Calculating average cadence is not supported for trashed facility: bfbc2l",
"host": "ip-10-1-18-233.us-west-2.compute.internal",
"pid": 1104873,
"region": "us-west-2",
"version": "production-us-west-2-20260410T0030Z0-045f9011-cupixworks"
}
4. 타임라인:
| 시각 (UTC) | 서비스 | 이벤트 |
|---|---|---|
| 2026-04-09T05:41:21Z | cupixworks-api |
PUT /api/v1/facilities/bfbc2l/trash -> 204 (user: jhangwon.yoon@cupix.io) |
| 2026-04-10T00:30:30Z | cupixworks-worker |
Cron: "Refreshing average cadence on 152 facilities by record creation" |
| 2026-04-10T00:30:44-46Z | cupixworks-worker |
48+ 성공: "Average cadence has updated on facility: XXX" |
| 2026-04-10T00:30:46Z | cupixworks-worker |
ERROR: "Failed to refresh average cadence on bfbc2l" |
5. 14일간 동일 에러 패턴 검색 — 2건 발생:
service:cupixworks-worker status:error "Failed to refresh average cadence" "not supported for trashed"
Time: now-14d
| 시각 | 환경 | Facility |
|---|---|---|
| 2026-04-10T00:30:46Z | production (us-west-2) | bfbc2l |
| 2026-04-03T00:30:29Z | qa (us-west-2) | 32yqde |
QA 환경에서도 동일한 패턴이 확인되어, 이는 체계적인 문제(systemic issue)입니다.
Fix Recommendation#
즉시 조치 (Critical)#
- 파일:
lib/cupix/cron/facility.rb:15및lib/cupix/cron/facility.rb:27 - 두 cron 메서드(
refresh_average_cadence_on_record_created,refresh_average_cadence_on_schedule)의 facility 쿼리에.untrashedscope를 추가하여 trashed facility를 제외해야 합니다. - 현재:
::Facility.where(id: ::Record.where('created_at > ?', 1.day.ago).pluck(:facility_id)) - 변경 방향:
.untrashed체인 추가
단기 개선 (1주 이내)#
refresh_cadence_candidatesscope가 이미analysis/facility.rb:6에 정의되어 있으므로, cron 메서드에서 이 scope를 활용하는 것을 검토해야 합니다. 다만, 이 scope는next_cadence_check_at과delay_status조건도 포함하고 있어 cron의 의도와 다를 수 있으므로 비즈니스 로직 확인이 필요합니다.
장기 개선 (재발 방지)#
- Facility 관련 batch 작업에서 trashed 상태 필터링을 누락하는 패턴이 반복될 수 있으므로, trashed facility를 자동으로 제외하는 default scope 도입 또는 코드 리뷰 체크리스트에 해당 항목을 추가하는 것을 검토해야 합니다.
Monitoring#
- 동일 에러 재발 모니터링:
service:cupixworks-worker status:error "Failed to refresh average cadence" "not supported for trashed"
Risk Assessment#
- Risk level: low
- 예상 복잡도: trivial —
.untrashedscope 추가만으로 해결 가능