ES /docs

CaptureRepository#update — InnoDB row-lock timeout

Fix Plan: CapturesController#update Lock Wait Timeout — 비동기 Worker 분리

Background#

state_machines-activerecord gem은 after_transition 콜백을 트랜잭션 내부에서 실행한다. Editing의 상태 전환 시 FORCE_APPLY_ENTITIES_STATUSES 콜백에서 N개 editing_entities를 순회하며 각 Capture row에 exclusive lock을 획득하므로, entity가 많을수록 lock 보유 시간이 선형 증가하여 동시 요청에 lock wait timeout(50s)을 유발한다. 이 heavy operation만 Sidekiq Worker로 분리하여 트랜잭션 내 lock 보유 시간을 최소화한다.

Changes#

tesla: app/workers/apply_entities_state_worker.rb (NEW)#

  • What: ApplyEntitiesStateWorker Sidekiq worker 신규 생성. editing_idstate 인자를 받아, editing의 untrashed editing_entities를 순회하며 #{state}_state! 호출.
  • Why: FORCE_APPLY_ENTITIES_STATUSES 콜백의 N개 entity cascading state transition을 트랜잭션 외부(비동기)로 분리하여 lock 보유 시간 최소화.
  • Lines: 전체 (신규 파일)

tesla: app/models/concerns/statable/editing.rb#

  • What: after_transition from: any, to: FORCE_APPLY_ENTITIES_STATUSES 콜백 본문을 ApplyEntitiesStateWorker.perform_async(model.id, transition.to_name.to_s)로 교체.
  • Why: 기존 inline 순회(N개 entity × save!)를 비동기 Worker 호출 1회로 변경하여 트랜잭션 내 lock 보유 시간 O(N) → O(1)로 감소.
  • Lines: 141-146

Acceptance Criteria#

  • app/workers/apply_entities_state_worker.rb 파일이 존재하고 ApplyEntitiesStateWorker 클래스를 정의
  • Worker가 include Sidekiq::Worker, sidekiq_options queue: :default, retry: 3 설정 포함
  • Worker의 perform(editing_id, state) 메서드에 nil guard (find_by + return if nil) 포함
  • statable/editing.rb line 141-146의 콜백 본문이 ApplyEntitiesStateWorker.perform_async(model.id, transition.to_name.to_s) 호출로 변경
  • 기존 inline each 순회 코드가 제거됨
  • ruby -c 문법 검증 통과 (두 파일 모두)

Tests#

  • 기존 테스트: spec 파일이 존재할 경우 bundle exec rspec spec/workers/apply_entities_state_worker_spec.rb (agent env에서는 ruby -c로 대체)
  • 신규 테스트: 없음 (agent env 제약)