AlchemyCMS/alchemy_cms

View on GitHub
app/models/alchemy/page_mutex.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
# frozen_string_literal: true

module Alchemy
  class PageMutex < BaseRecord
    class LockFailed < StandardError; end

    MAX_AGE = 300 # seconds

    belongs_to :page, class_name: "Alchemy::Page", optional: true

    scope :expired, -> { where(arel_table[:created_at].lteq(MAX_AGE.seconds.ago)) }

    def self.with_lock!(page)
      raise ArgumentError, "A page is necessary to lock it" if page.nil?

      # remove old expired page if it wasn't deleted before
      expired.where(page: page).delete_all

      begin
        page_mutex = create!(page: page)
      rescue ActiveRecord::RecordNotUnique
        error = LockFailed.new("Can't lock page #{page.id} twice!")
        logger.error error.inspect
        raise error
      end
      yield
    ensure
      page_mutex&.destroy
    end
  end
end