|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +# Released under the MIT License. |
| 4 | +# Copyright, 2026, by Samuel Williams. |
| 5 | + |
| 6 | +require "async/service/generic" |
| 7 | + |
| 8 | +require_relative "server" |
| 9 | + |
| 10 | +module Falcon |
| 11 | + # @namespace |
| 12 | + module Service |
| 13 | + # A managed service for running Falcon workers with independently bound endpoints. |
| 14 | + class Cluster < Server |
| 15 | + # Start the service without binding the endpoint in the parent process. |
| 16 | + def start |
| 17 | + preload! |
| 18 | + |
| 19 | + Async::Service::Generic.instance_method(:start).bind_call(self) |
| 20 | + end |
| 21 | + |
| 22 | + # Setup the service into the specified container. |
| 23 | + # @parameter container [Async::Container] The container to configure. |
| 24 | + def setup(container) |
| 25 | + container_options = @evaluator.container_options |
| 26 | + health_check_timeout = container_options[:health_check_timeout] |
| 27 | + |
| 28 | + container.run(**container_options) do |instance| |
| 29 | + clock = Async::Clock.start |
| 30 | + |
| 31 | + Async do |
| 32 | + evaluator = self.environment.evaluator |
| 33 | + server = nil |
| 34 | + |
| 35 | + health_checker(instance, health_check_timeout) do |
| 36 | + if server |
| 37 | + instance.name = format_title(evaluator, server) |
| 38 | + end |
| 39 | + end |
| 40 | + |
| 41 | + instance.status!("Preparing...") |
| 42 | + |
| 43 | + bound_endpoint = evaluator.endpoint.bound |
| 44 | + evaluator.bound_endpoint = bound_endpoint |
| 45 | + |
| 46 | + evaluator.prepare!(instance) |
| 47 | + emit_prepared(instance, clock) |
| 48 | + |
| 49 | + instance.status!("Running...") |
| 50 | + server = run(instance, evaluator, bound_endpoint) |
| 51 | + instance.name = format_title(evaluator, server) |
| 52 | + emit_running(instance, clock) |
| 53 | + |
| 54 | + instance.ready! |
| 55 | + end |
| 56 | + end |
| 57 | + end |
| 58 | + |
| 59 | + # Run the service logic. |
| 60 | + # |
| 61 | + # @parameter instance [Object] The container instance. |
| 62 | + # @parameter evaluator [Environment::Evaluator] The environment evaluator. |
| 63 | + # @parameter bound_endpoint [IO::Endpoint] The endpoint bound by this worker. |
| 64 | + # @returns [Falcon::Server] The server instance. |
| 65 | + def run(instance, evaluator, bound_endpoint) |
| 66 | + server = evaluator.make_server(bound_endpoint) |
| 67 | + |
| 68 | + Async do |task| |
| 69 | + server.run |
| 70 | + |
| 71 | + task.children&.each(&:wait) |
| 72 | + end |
| 73 | + |
| 74 | + server |
| 75 | + end |
| 76 | + end |
| 77 | + end |
| 78 | +end |
0 commit comments