lib/async/container/controller.rb in async-container-0.14.1 vs lib/async/container/controller.rb in async-container-0.15.0

- old
+ new

@@ -16,52 +16,104 @@ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -require_relative 'terminator' +require_relative 'error' +require_relative 'best' -require 'async/reactor' +require_relative 'statistics' module Async module Container + class ContainerFailed < Error + def initialize(container) + super("Could not create container!") + @container = container + end + + attr :container + end + + # Manages the life-cycle of a container. class Controller - def initialize - @attached = [] + SIGHUP = Signal.list["HUP"] + DEFAULT_TIMEOUT = 2 + + def initialize(startup_duration: DEFAULT_TIMEOUT) + @container = nil + + @startup_duration = startup_duration end - def attach(controller = nil, &block) - if controller - @attached << controller + attr :container + + def create_container + Container.new + end + + def setup(container) + end + + def start + self.restart + end + + def stop(graceful = true) + @container&.stop(graceful) + @container = nil + end + + def restart(duration = @startup_duration) + hup_action = Signal.trap(:HUP, :IGNORE) + container = self.create_container + + begin + self.setup(container) + rescue + raise ContainerFailed, container end - if block_given? - @attached << Terminator.new(&block) + Async.logger.debug(self, "Waiting for startup...") + container.sleep(duration) + Async.logger.debug(self, "Finished startup.") + + if container.failed? + container.stop + + raise ContainerFailed, container end - return self + @container&.stop + @container = container + ensure + Signal.trap(:HUP, hup_action) end - def async(**options, &block) - spawn(**options) do |instance| + def run + Async.logger.debug(self) {"Starting container..."} + + self.start + + while true begin - Async::Reactor.run(instance, &block) - rescue Interrupt - # Graceful exit. + @container.wait + rescue SignalException => exception + if exception.signo == SIGHUP + Async.logger.info(self) {"Reloading container..."} + + begin + self.restart + rescue ContainerFailed => failure + Async.logger.error(self) {failure} + end + else + raise + end end end - end - - def run(count: Container.processor_count, **options, &block) - count.times do - async(**options, &block) - end - - return self - end - - def stop(graceful = true) - @attached.each(&:stop) + ensure + self.stop end end end end