Sha256: 796c5c589f6bc270c97c13d49ec1ad2f91ea94d20514124cc3921e8f4b960fec

Contents?: true

Size: 1.83 KB

Versions: 44

Compression:

Stored size: 1.83 KB

Contents

# frozen_string_literal: true

module MalawiHivProgramReports
  module Utils
    module ConcurrencyUtils
      LOCK_FILES_DIR_PATH = Rails.root.join('tmp', 'locks')

      ##
      # Acquire a lock and run the given block of code.
      #
      # The locking mechanism uses files to allow for blocking across processes.
      # This is useful for example in situations where you only want to run one
      # instance of a report.
      #
      # Parameters:
      #   lock_file_path: A relative path to the lock file (allows for namespacing your locks, eg art_service/regimens.lock)
      #   blocking: If lock can not be acquired wait else throw an error (defaults to true)
      #
      # Raises:
      #   FailedToAcquireLock: When lock couldn't be acquired and blocking is set to false
      #
      # Usage:
      #   class Someclass
      #     include ModelUtils
      #
      #     def do_something
      #       with_lock('mylockfile.lock') do
      #         # Run some task requiring exclusive access to some resource
      #       end
      #     end
      #   end
      #
      #   SomeClass.new.do_something
      def with_lock(lock_file_path, blocking: true)
        path = LOCK_FILES_DIR_PATH.join(lock_file_path)

        unless Dir.exist?(path.dirname)
          Rails.logger.debug("Creating lock file directory: #{path.dirname}")
          ::FileUtils.mkdir_p(path.dirname)
        end

        File.open(path, 'w') do |lock_file|
          Rails.logger.debug("Attempting to acquire lock: #{lock_file_path}")
          locked = lock_file.flock(blocking ? File::LOCK_EX : File::LOCK_NB | File::LOCK_EX)
          raise ::FailedToAcquireLock, "Lock #{lock_file_path} is locked by another process" if !locked && !blocking

          lock_file.write("Locked by process ##{Process.pid} at #{Time.now}")
          yield
        end
      end
    end
  end
end

Version data entries

44 entries across 44 versions & 1 rubygems

Version Path
malawi_hiv_program_reports-1.0.5 app/services/malawi_hiv_program_reports/utils/concurrency_utils.rb
malawi_hiv_program_reports-1.0.4 app/services/malawi_hiv_program_reports/utils/concurrency_utils.rb
malawi_hiv_program_reports-1.0.3 app/services/malawi_hiv_program_reports/utils/concurrency_utils.rb
malawi_hiv_program_reports-1.0.2 app/services/malawi_hiv_program_reports/utils/concurrency_utils.rb