From e752df1b3c3d5168ebdc4eb41270f313738e27a6 Mon Sep 17 00:00:00 2001 From: Felix Auringer <48409110+felixauringer@users.noreply.github.com> Date: Tue, 27 Jul 2021 13:40:50 +0200 Subject: [PATCH] Move EventMachine initialization to Runner::EventLoop --- app/models/runner.rb | 17 ----------------- lib/runner/event_loop.rb | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/app/models/runner.rb b/app/models/runner.rb index 30fa48a1..ee66a28b 100644 --- a/app/models/runner.rb +++ b/app/models/runner.rb @@ -41,7 +41,6 @@ class Runner < ApplicationRecord end def attach_to_execution(command, &block) - ensure_event_machine starting_time = Time.zone.now begin # As the EventMachine reactor is probably shared with other threads, we cannot use EventMachine.run with @@ -66,22 +65,6 @@ class Runner < ApplicationRecord private - # If there are multiple threads trying to connect to the WebSocket of their execution at the same time, - # the Faye WebSocket connections will use the same reactor. We therefore only need to start an EventMachine - # if there isn't a running reactor yet. - # See this StackOverflow answer: https://stackoverflow.com/a/8247947 - def ensure_event_machine - unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive? - event_loop = Runner::EventLoop.new - Thread.new do - EventMachine.run { event_loop.stop } - ensure - ActiveRecord::Base.connection_pool.release_connection - end - event_loop.wait - end - end - def request_id request_new_id if runner_id.blank? end diff --git a/lib/runner/event_loop.rb b/lib/runner/event_loop.rb index ff30cc77..037f08d0 100644 --- a/lib/runner/event_loop.rb +++ b/lib/runner/event_loop.rb @@ -5,6 +5,7 @@ class Runner::EventLoop def initialize @queue = Queue.new + ensure_event_machine end # wait waits until another thread calls stop on this EventLoop. @@ -19,4 +20,22 @@ class Runner::EventLoop def stop @queue.push nil if @queue.empty? end + + private + + # If there are multiple threads trying to connect to the WebSocket of their execution at the same time, + # the Faye WebSocket connections will use the same reactor. We therefore only need to start an EventMachine + # if there isn't a running reactor yet. + # See this StackOverflow answer: https://stackoverflow.com/a/8247947 + def ensure_event_machine + unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive? + queue = Queue.new + Thread.new do + EventMachine.run { queue.push nil } + ensure + ActiveRecord::Base.connection_pool.release_connection + end + queue.pop + end + end end