stefan-kolb/nucleus

View on GitHub
lib/nucleus/adapters/v1/heroku/app_states.rb

Summary

Maintainability
A
1 hr
Test Coverage
module Nucleus
  module Adapters
    module V1
      class Heroku < Stub
        # AppStates for Heroku, or the logic to determine the current application state
        module AppStates
          private

          def application_state(app, retrieved_dynos = nil)
            # 1: created, both repo and slug are nil
            return Enums::ApplicationStates::CREATED unless repo_or_slug_content?(app)

            # all subsequent states require dynos to be determined
            dynos = retrieved_dynos ? retrieved_dynos : dynos(app[:id])

            # 2: deployed if no dynos assigned
            return Enums::ApplicationStates::DEPLOYED if dynos.empty?

            # 3: stopped if maintenance
            return Enums::ApplicationStates::STOPPED if app[:maintenance] || dynos_not_running?(dynos)

            # 4: running if no maintenance (checked above) and at least ony dyno is up
            return Enums::ApplicationStates::RUNNING if dyno_states(dynos).include?('up')

            # 5: idle if all dynos are idling
            return Enums::ApplicationStates::IDLE if dynos_idle?(dynos)

            # arriving here the above states do not catch all states of the Heroku app, which should not happen ;-)
            log.debug("Faild to determine state for: #{app}, #{dynos}")
            raise Errors::UnknownAdapterCallError, 'Could not determine app state. Please verify the Heroku adapter'
          end

          def repo_or_slug_content?(app)
            return true if !app[:repo_size].nil? && app[:repo_size].to_i > 0
            return true if !app[:slug_size].nil? && app[:slug_size].to_i > 0
            false
          end

          def dyno_states(dynos)
            dynos.collect { |dyno| dyno[:state] }.compact.uniq
          end

          def dynos_idle?(dynos)
            dyno_states = dyno_states(dynos)
            dyno_states.length == 1 && dyno_states[0] == 'idle'
          end

          def dynos_not_running?(dynos)
            dynos.empty? || dyno_states(dynos).reject do |state|
              %w[crashed down starting].include?(state)
            end.empty?
          end
        end
      end
    end
  end
end