mirror of
https://github.com/hatchet-dev/hatchet.git
synced 2026-04-20 08:42:45 -05:00
* feat: initial ruby sdk * fix: run listener * fix: scope * feat: rest feature clients * fix: bugs * fix: concurrent register * fix: tests and ergonomics * docs: all of them * chore: lint * feat: add RBS * feat: add GitHub Actions workflow for Ruby SDK with linting, testing, and publishing steps * chore: lint * refactor: simplify load path setup for Hatchet REST client and remove symlink creation * fix: cert path * fix: test * fix: blocking * fix: ensure Hatchet client is only initialized once across examples * fix: tests * remove: unused example * fix: bubble up errors * test: skip flaky for now * remove: lifespans * fix: durable context bugs * fix: bulk replay * fix: tests * cleanup: generate tooling * fix: integration test * chore: lint * release: 0.1.0 * chore: remove python comments * refactor: remove OpenTelemetry configuration and related unused options * fix: default no healthcheck * chore: lockfile * feat: register as ruby * chore: lint * chore: update py/ts apis to include ruby * chore: docs pass * chore: lint * chore: generate * chore: cleanup * chore: generate examples * tests: add e2e tests * tests: cache examples dependencies * fix: namespace * fix: namespace * fix: namespaces * chore:lint * fix: improve cancellation workflow polling logic and add error handling * revert: py/ts versions
98 lines
2.4 KiB
Ruby
98 lines
2.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "open3"
|
|
require "net/http"
|
|
require "logger"
|
|
require "timeout"
|
|
|
|
module HatchetWorkerFixture
|
|
LOGGER = Logger.new($stdout)
|
|
|
|
# Wait for the worker health check endpoint to respond
|
|
#
|
|
# @param port [Integer] Health check port
|
|
# @param max_attempts [Integer] Maximum number of attempts
|
|
# @return [Boolean] true if healthy
|
|
# @raise [RuntimeError] if worker fails to start
|
|
def self.wait_for_worker_health(port:, max_attempts: 25)
|
|
attempts = 0
|
|
|
|
loop do
|
|
if attempts > max_attempts
|
|
raise "Worker failed to start within #{max_attempts} seconds"
|
|
end
|
|
|
|
begin
|
|
uri = URI("http://localhost:#{port}/health")
|
|
response = Net::HTTP.get_response(uri)
|
|
return true if response.code == "200"
|
|
rescue StandardError
|
|
# Worker not ready yet
|
|
end
|
|
|
|
sleep 1
|
|
attempts += 1
|
|
end
|
|
end
|
|
|
|
# Start a worker subprocess and wait for it to be healthy
|
|
#
|
|
# @param command [Array<String>] Command to run
|
|
# @param healthcheck_port [Integer] Port for health checks
|
|
# @yield [pid] Yields the process PID
|
|
# @return [void]
|
|
def self.with_worker(command, healthcheck_port: 8001)
|
|
LOGGER.info("Starting background worker: #{command.join(' ')}")
|
|
|
|
ENV["HATCHET_CLIENT_WORKER_HEALTHCHECK_PORT"] = healthcheck_port.to_s
|
|
|
|
stdin, stdout, stderr, wait_thr = Open3.popen3(*command)
|
|
pid = wait_thr.pid
|
|
|
|
# Log output in background threads
|
|
Thread.new do
|
|
stdout.each_line { |line| puts line.chomp }
|
|
rescue IOError
|
|
# Stream closed
|
|
end
|
|
|
|
Thread.new do
|
|
stderr.each_line { |line| $stderr.puts line.chomp }
|
|
rescue IOError
|
|
# Stream closed
|
|
end
|
|
|
|
wait_for_worker_health(port: healthcheck_port)
|
|
|
|
yield pid
|
|
ensure
|
|
LOGGER.info("Cleaning up background worker (PID: #{pid})")
|
|
|
|
if pid
|
|
begin
|
|
# Kill process group to get children too
|
|
Process.kill("TERM", -Process.getpgid(pid))
|
|
rescue Errno::ESRCH, Errno::EPERM
|
|
# Process already gone
|
|
end
|
|
|
|
begin
|
|
Timeout.timeout(5) { Process.wait(pid) }
|
|
rescue Timeout::Error
|
|
begin
|
|
Process.kill("KILL", pid)
|
|
Process.wait(pid)
|
|
rescue Errno::ESRCH, Errno::ECHILD
|
|
# Already gone
|
|
end
|
|
rescue Errno::ECHILD
|
|
# Already reaped
|
|
end
|
|
end
|
|
|
|
[stdin, stdout, stderr].each do |io|
|
|
io&.close rescue nil
|
|
end
|
|
end
|
|
end
|