require 'lib/executors/stack_executor'

class StackSyncWorker < Worker

  MAX_LOCK_WAITING_TIME = 15000

  # @options:
  #   'stack_name'    required
  #   'created_by'  optional
  def perform(options)
    call do |out, task|
      stack_name = options.fetch('stack_name')
      @created_by = options['created_by'] || ::Devops::Model::JobTask::SYSTEM_OWNER
      #TODO: mongoid query
      @stack = mongo.stack(stack_name)

      set_task_data({
        "created_by" => @created_by,
        "project" => @stack.project,
        "environment" => @stack.environment,
        "category" => @stack.category,
        "type" => Devops::Model::JobTask::SYNC_STACK_TYPE,
        "subtasks" => [],
        "stack" => @stack.name
      })

      wait_until_stack_is_unlocked
      puts_and_flush 'Persisting new servers.'
      executor.persist_new_servers

      puts_and_flush "\n\nDeleting stale servers."
      executor.delete_stale_servers

      puts_and_flush "\n\nBootstrapping just persisted servers."
      bootstrap_result = executor.bootstrap_just_persisted(jid)
      puts_and_flush Devops::Messages.t("worker.stack_sync.bootstrap_result.#{bootstrap_result.reason}")
      bootstrap_result.code
    end
  end

  private

  def executor
    @executor ||= Devops::Executor::StackExecutor.new(out: out, stack: @stack, current_user: @created_by)
  end

  def wait_until_stack_is_unlocked
    return unless @stack.persisting_is_locked
    puts_and_flush 'Stack is locked, waiting...'
    waiting_time = 0
    sleep_time = 10
    loop do
      sleep(sleep_time)
      @stack = mongo.stack(@stack.name)
      return unless @stack.persisting_is_locked

      waiting_time += sleep_time
      raise "Stack has been locked for too long" if waiting_time > MAX_LOCK_WAITING_TIME
    end
  end

end
