# frozen_string_literal: true module Sessions class AssertUserConcurrent ERROR_CODE = "user_concurrent_stream" def self.with_lock(session, action: "start") new(session, action: action).with_lock { yield } end def initialize(session, action: "start") @session = session @action = action.to_s end def with_lock occupying = nil User.transaction do User.lock.find(@session.user_id) if @session.user_id.present? occupying = occupying_session yield if occupying.nil? end return if occupying.nil? StreamConcurrencyViolation.record!( attempted: @session, occupying: occupying, action: @action ) raise Teams::EntitlementError.new( I18n.t("api.errors.user_concurrent_stream"), code: ERROR_CODE ) end private def occupying_session return if @session.user_id.blank? StreamSession.broadcasting .where(user_id: @session.user_id) .where.not(id: @session.id) .includes(:user, match: { team: :club }) .order(Arel.sql("COALESCE(started_at, updated_at) DESC")) .first end end end