Skip to content

Commit

Permalink
Merge pull request #472 from basecamp/move-healthcheck-poller-to-cli
Browse files Browse the repository at this point in the history
Healthcheck polling is a CLI concern
  • Loading branch information
dhh authored Sep 16, 2023
2 parents ff4d025 + 59ac59d commit ec8192b
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 71 deletions.
4 changes: 2 additions & 2 deletions lib/kamal/cli/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ def boot

execute *app.run(hostname: "#{host}-#{SecureRandom.hex(6)}")

Kamal::Utils::HealthcheckPoller.wait_for_healthy(pause_after_ready: true) { capture_with_info(*app.status(version: version)) }
Kamal::Cli::Healthcheck::Poller.wait_for_healthy(pause_after_ready: true) { capture_with_info(*app.status(version: version)) }

if old_version.present?
if role_config.uses_cord?
cord = capture_with_info(*app.cord(version: old_version), raise_on_non_zero_exit: false).strip
if cord.present?
execute *app.cut_cord(cord)
Kamal::Utils::HealthcheckPoller.wait_for_unhealthy(pause_after_ready: true) { capture_with_info(*app.status(version: old_version)) }
Kamal::Cli::Healthcheck::Poller.wait_for_unhealthy(pause_after_ready: true) { capture_with_info(*app.status(version: old_version)) }
end
end

Expand Down
4 changes: 2 additions & 2 deletions lib/kamal/cli/healthcheck.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ def perform
on(KAMAL.primary_host) do
begin
execute *KAMAL.healthcheck.run
Kamal::Utils::HealthcheckPoller.wait_for_healthy { capture_with_info(*KAMAL.healthcheck.status) }
rescue Kamal::Utils::HealthcheckPoller::HealthcheckError => e
Poller.wait_for_healthy { capture_with_info(*KAMAL.healthcheck.status) }
rescue Poller::HealthcheckError => e
error capture_with_info(*KAMAL.healthcheck.logs)
error capture_with_pretty_json(*KAMAL.healthcheck.container_health_log)
raise
Expand Down
64 changes: 64 additions & 0 deletions lib/kamal/cli/healthcheck/poller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
module Kamal::Cli::Healthcheck::Poller
extend self

TRAEFIK_UPDATE_DELAY = 5

class HealthcheckError < StandardError; end

def wait_for_healthy(pause_after_ready: false, &block)
attempt = 1
max_attempts = KAMAL.config.healthcheck["max_attempts"]

begin
case status = block.call
when "healthy"
sleep TRAEFIK_UPDATE_DELAY if pause_after_ready
when "running" # No health check configured
sleep KAMAL.config.readiness_delay if pause_after_ready
else
raise HealthcheckError, "container not ready (#{status})"
end
rescue HealthcheckError => e
if attempt <= max_attempts
info "#{e.message}, retrying in #{attempt}s (attempt #{attempt}/#{max_attempts})..."
sleep attempt
attempt += 1
retry
else
raise
end
end

info "Container is healthy!"
end

def wait_for_unhealthy(pause_after_ready: false, &block)
attempt = 1
max_attempts = KAMAL.config.healthcheck["max_attempts"]

begin
case status = block.call
when "unhealthy"
sleep TRAEFIK_UPDATE_DELAY if pause_after_ready
else
raise HealthcheckError, "container not unhealthy (#{status})"
end
rescue HealthcheckError => e
if attempt <= max_attempts
info "#{e.message}, retrying in #{attempt}s (attempt #{attempt}/#{max_attempts})..."
sleep attempt
attempt += 1
retry
else
raise
end
end

info "Container is unhealthy!"
end

private
def info(message)
SSHKit.config.output.info(message)
end
end
64 changes: 0 additions & 64 deletions lib/kamal/utils/healthcheck_poller.rb

This file was deleted.

4 changes: 2 additions & 2 deletions test/cli/healthcheck_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class CliHealthcheckTest < CliTestCase
# Prevent expected failures from outputting to terminal
Thread.report_on_exception = false

Kamal::Utils::HealthcheckPoller.stubs(:sleep) # No sleeping when retrying
Kamal::Cli::Healthcheck::Poller.stubs(:sleep) # No sleeping when retrying
Kamal::Configuration.any_instance.stubs(:run_id).returns("12345678901234567890123456789012")

SSHKit::Backend::Abstract.any_instance.stubs(:execute)
Expand Down Expand Up @@ -35,7 +35,7 @@ class CliHealthcheckTest < CliTestCase
# Prevent expected failures from outputting to terminal
Thread.report_on_exception = false

Kamal::Utils::HealthcheckPoller.stubs(:sleep) # No sleeping when retrying
Kamal::Cli::Healthcheck::Poller.stubs(:sleep) # No sleeping when retrying

SSHKit::Backend::Abstract.any_instance.stubs(:execute)
.with(:docker, :container, :ls, "--all", "--filter", "name=^healthcheck-app-999$", "--quiet", "|", :xargs, :docker, :stop, raise_on_non_zero_exit: false)
Expand Down
2 changes: 1 addition & 1 deletion test/cli/main_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ class CliMainTest < CliTestCase
test "rollback without old version" do
Kamal::Cli::Main.any_instance.stubs(:container_available?).returns(true)

Kamal::Utils::HealthcheckPoller.stubs(:sleep)
Kamal::Cli::Healthcheck::Poller.stubs(:sleep)

SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
.with(:docker, :container, :ls, "--all", "--filter", "name=^app-web-123$", "--quiet", raise_on_non_zero_exit: false)
Expand Down

0 comments on commit ec8192b

Please sign in to comment.