Dynflow / dynflow

DYNamic workFLOW orchestration engine
http://dynflow.github.io
MIT License
121 stars 44 forks source link

Daemon in background mode crashing repeatedly #322

Open Fred-JulieDesk opened 5 years ago

Fred-JulieDesk commented 5 years ago

Hello,

It seems there is a problem in the 'run_background' method of the rails daemon, the '::Logging' class does not exists

def run_background(command = 'start', options = {})
        options = default_options.merge(options)
        FileUtils.mkdir_p(options[:pid_dir])
        begin
          require 'daemons'
        rescue LoadError
          raise "You need to add gem 'daemons' to your Gemfile if you wish to use it."
        end

        unless %w(start stop restart run).include?(command)
          raise "Command exptected to be 'start', 'stop', 'restart', 'run', was #{command.inspect}"
        end

        STDOUT.puts("Dynflow Executor: #{command} in progress")

        options[:executors_count].times do
          daemons_class.run_proc(
            options[:process_name],
            daemons_options(command, options)
          ) do |*_args|
            begin
              ::Logging.reopen
              run(options[:rails_root], options)
            rescue => e
              Logger.new(File.join(options[:rails_root], 'log/daemon.log')).error(e.inspect)
              STDERR.puts e.message
              ::Rails.logger.fatal('Failed running Dynflow daemon')
              ::Rails.logger.fatal(e)
              exit 1
            end
          end
        end
      end

It causes the daemon to crash unexpectedly and silently as no logs are being emitted (Rails.logger does not log in any files at this point of time due to the daemonizing process)

I do not see the point of this reopen method maybe just deleting the line would be ok

adamruzicka commented 5 years ago

How are you trying to run it?

Fred-JulieDesk commented 5 years ago

In a rake task in my rails app

args[:executors_count].to_i.times do |i| daemon.run_background('start', {executors_count: 1, process_name: "dynflowexecutor#{i}"}) end

By the way, for Dynflow to work with Rails I had to hack around and do

dynflow_engine = Dynflow::Rails.new Rails.application.define_singleton_method(:dynflow) { dynflow_engine } dynflow_engine.require!

Prior to be able to use Dynflow at all with Rails

adamruzicka commented 5 years ago

In Foreman we use the Logging gem for logging, but in order for logging to work, the file descriptors need to be reopened after a fork. That's why we can't just delete the line. We could however either check if ::Logging is defined or explicitly require it.

About the hacking part, take a look how it's done in Foreman https://github.com/theforeman/foreman/blob/develop/config/application.rb#L300https://github.com/theforeman/foreman/blob/develop/config/application.rb#L300

Fred-JulieDesk commented 5 years ago

Thanks for the example but if I do like you suggest

@dynflow =
        if defined?(ForemanTasks)
          ForemanTasks.dynflow
        else
          ::Dynflow::Rails.new(nil, ::Foreman::Dynflow::Configuration.new)
        end
@dynflow.require!
@dynflow

In the context of a Rails application I got the following error

/Users/gtrgrt/.rvm/gems/ruby-2.6.1/gems/dynflow-1.2.1/lib/dynflow/rails/configuration.rb:84:in 'remote?': undefined method `dynflow' for #<MyProject::Application:0x00007f9f1823eee8> (NoMethodError)

Which is why I had to use the following hack

dynflow_engine = Dynflow::Rails.new(nil, CustomDynflowConfig.new(true))
Rails.application.define_singleton_method(:dynflow) { dynflow_engine }
dynflow_engine.require!
dynflow_engine.initialize!

I'm not sure how you get it working in Foreman