Class: WideEvent::Setup::Checker

Inherits:
Object
  • Object
show all
Defined in:
lib/wide_event/setup/checker.rb

Overview

The single entry point behind bin/rails wide_events:setup:check. Re-derives everything it needs from the app's own generated files (config/deploy.yml, .kamal/wide-events-*-token) so the same command is correct with no flags whether it is run before the first kamal setup, while waiting on DNS, or against an already-deployed store.

Every check that would otherwise touch the outside world - running kamal, sleeping, resolving DNS, or calling the store over HTTP - goes through an injected seam (runner/sleeper/resolver/http_get/ client_factory) so tests never shell out, sleep for real, or hit a real network.

Defined Under Namespace

Classes: Result

Constant Summary collapse

MIN_KAMAL_VERSION =
WideEvent::Kamal::DeployEditor::MINIMUM_VERSION
DNS_TIMEOUT_SECONDS =
120
DNS_POLL_INTERVAL_SECONDS =
3
RESUME_COMMAND =
"bin/rails wide_events:setup:check"
DEPLOY_YML_RELATIVE_PATH =
"config/deploy.yml"
OPEN_TIMEOUT =
3
READ_TIMEOUT =
5
QUERY_DEADLINE =
15
NETWORK_ERRORS =
[
  Net::OpenTimeout, Net::ReadTimeout, Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ECONNRESET,
  SocketError, OpenSSL::SSL::SSLError, EOFError, IOError
].freeze
ROUTE_STATS_SQL =
<<~SQL.strip
  SELECT route, count(*) AS requests, quantile_cont(duration_ms, 0.95) AS p95_ms
  FROM wide_events
  WHERE occurred_at > current_timestamp - INTERVAL 1 DAY
  GROUP BY route
  ORDER BY requests DESC
  LIMIT 20
SQL

Instance Method Summary collapse

Constructor Details

#initialize(root:, runner: CommandRunner.new, clock: -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) }, sleeper: ->(seconds) { sleep(seconds) }, resolver: method(:default_resolve), http_get: method(:default_http_get), client_factory: method(:default_client_factory), uuid: -> { SecureRandom.uuid }, wall_clock: -> { Time.now }) ⇒ Checker

Returns a new instance of Checker.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/wide_event/setup/checker.rb', line 62

def initialize(root:, runner: CommandRunner.new, clock: -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) },
               sleeper: ->(seconds) { sleep(seconds) }, resolver: method(:default_resolve),
               http_get: method(:default_http_get), client_factory: method(:default_client_factory),
               uuid: -> { SecureRandom.uuid }, wall_clock: -> { Time.now })
  @root = root.to_s
  @runner = runner
  @clock = clock
  @sleeper = sleeper
  @resolver = resolver
  @http_get = http_get
  @client_factory = client_factory
  @uuid = uuid
  @wall_clock = wall_clock
end

Instance Method Details

#runObject



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/wide_event/setup/checker.rb', line 77

def run
  checks = {}

  config = load_deploy_config
  unless config[:ok]
    checks[:deploy_config] = false
    return build_result("failed", checks, config[:error])
  end
  checks[:deploy_config] = true

  version = check_kamal_version
  checks[:kamal_version] = version[:ok]
  return build_result("failed", checks, version[:message]) unless version[:ok]

  kamal_config = check_kamal_config
  checks[:kamal_config] = kamal_config[:ok]
  return build_result("failed", checks, kamal_config[:message]) unless kamal_config[:ok]

  directory = check_host_directory(config)
  checks[:host_directory] = directory[:ok]
  return build_result("failed", checks, directory[:message]) unless directory[:ok]

  dns = check_dns(config)
  checks[:dns] = dns[:ok]
  return build_result(dns[:state], checks, dns[:message]) unless dns[:ok]

  endpoint = check_endpoint(config)
  checks[:endpoint] = endpoint[:state] == :healthy
  case endpoint[:state]
  when :ready_to_deploy then return build_result("ready_to_deploy", checks, endpoint[:message])
  when :degraded then return build_result("degraded", checks, endpoint[:message])
  when :failed then return build_result("failed", checks, endpoint[:message])
  end

  synthetic = run_synthetic_round_trip(config)
  checks[:synthetic] = synthetic[:ok]
  return build_result("failed", checks, synthetic[:message]) unless synthetic[:ok]

  build_result("healthy", checks, synthetic[:message])
end