104 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Ruby
		
	
	
	
# frozen_string_literal: true
 | 
						|
 | 
						|
module Gitlab
 | 
						|
  # DEPRECATED. Use Gitlab::BackgroundTask for new code instead.
 | 
						|
  class Daemon
 | 
						|
    # Options:
 | 
						|
    # - recreate: We usually only allow a single instance per process to exist;
 | 
						|
    #             this can be overridden with this switch, so that existing
 | 
						|
    #             instances are stopped and recreated.
 | 
						|
    def self.initialize_instance(*args, recreate: false, **options)
 | 
						|
      if @instance
 | 
						|
        if recreate
 | 
						|
          @instance.stop
 | 
						|
        else
 | 
						|
          raise "#{name} singleton instance already initialized"
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      @instance = new(*args, **options)
 | 
						|
      Kernel.at_exit(&@instance.method(:stop))
 | 
						|
      @instance
 | 
						|
    end
 | 
						|
 | 
						|
    def self.instance(...)
 | 
						|
      @instance ||= initialize_instance(...)
 | 
						|
    end
 | 
						|
 | 
						|
    attr_reader :thread
 | 
						|
 | 
						|
    def thread?
 | 
						|
      !thread.nil?
 | 
						|
    end
 | 
						|
 | 
						|
    # Possible options:
 | 
						|
    # - synchronous [Boolean] if true, turns `start` into a blocking call
 | 
						|
    def initialize(**options)
 | 
						|
      @synchronous = options[:synchronous]
 | 
						|
      @mutex = Mutex.new
 | 
						|
    end
 | 
						|
 | 
						|
    def enabled?
 | 
						|
      true
 | 
						|
    end
 | 
						|
 | 
						|
    def thread_name
 | 
						|
      self.class.name.demodulize.underscore
 | 
						|
    end
 | 
						|
 | 
						|
    def start
 | 
						|
      return unless enabled?
 | 
						|
 | 
						|
      @mutex.synchronize do
 | 
						|
        break thread if thread?
 | 
						|
 | 
						|
        if start_working
 | 
						|
          @thread = Thread.new do
 | 
						|
            Thread.current.name = thread_name
 | 
						|
            run_thread
 | 
						|
          end
 | 
						|
 | 
						|
          @thread.join if @synchronous
 | 
						|
 | 
						|
          @thread
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    def stop
 | 
						|
      @mutex.synchronize do
 | 
						|
        break unless thread?
 | 
						|
 | 
						|
        stop_working
 | 
						|
 | 
						|
        if thread
 | 
						|
          thread.wakeup if thread.alive?
 | 
						|
          begin
 | 
						|
            thread.join unless Thread.current == thread
 | 
						|
          rescue Exception # rubocop:disable Lint/RescueException
 | 
						|
          end
 | 
						|
          @thread = nil
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    private
 | 
						|
 | 
						|
    # Executed in lock context before starting thread
 | 
						|
    # Needs to return success
 | 
						|
    def start_working
 | 
						|
      true
 | 
						|
    end
 | 
						|
 | 
						|
    # Executed in separate thread
 | 
						|
    def run_thread
 | 
						|
      raise NotImplementedError
 | 
						|
    end
 | 
						|
 | 
						|
    # Executed in lock context
 | 
						|
    def stop_working
 | 
						|
      # no-ops
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |