adamwiggins / clockwork

A scheduler process to replace cron
663 stars 185 forks source link

Rails Error: Unable to access log file #3

Open leifbladt opened 13 years ago

leifbladt commented 13 years ago

I have a Rails 3 application which uses delayed_job as job queue. When I use clockwork with the following configuration, I get an error that the rails process can't access the log file.

require File.expand_path('../config/environment', File.dirname(__FILE__))
every(60.seconds, 'check') { Delayed::Job.enqueue(SchedulerJob.new) }
Rails Error: Unable to access log file. Please ensure that  exists and is chmod 0666. The log level has been raised to WARN and the output directed to STDERR until the problem is fixed.

I already checked the permissions of the log file.

Versions used: Rails 3.0.5 Ruby 1.9.2-p136 delayed_job 2.1.4 clockwork 0.2.3

sdhull commented 13 years ago

Yeah this was bugging me to. I suspect it has something to do with the fact that ever since Ruby 1.9, the ruby interpreter doesn't seem to set pwd properly (for me, anyway). So for example, if I want to run tests, I have to do something like this: ruby -I . test/some_test.rb It's very annoying. Anyway so I think the issue is that Ruby doesn't know that pwd = Rails.root when you simply run your clock.rb file. I solved this personally by created a rake task (since loading your environment in rake knows how to write to your log file), that pretty much does the same thing as running clockwork clock.rb. For a bonus, I daemonize it, save the pid, and created rake tasks for start, stop, and restart. Check it out: https://gist.github.com/938386

Enjoy. :)

juno commented 13 years ago

I had same error on ruby 1.9.2p180 & rails 3.0.9. I think that this error caused by naming conflicts of log method.

bin/clockwork includes Clockwork module into top-level namespace, thus, log method call will invoke Clockwork::log(msg) instead of rails expects.

So, if Rails.root/clock.rb loads Rails environment likes this:

require './config/boot'
require './config/environment'

handler { |job| puts "Process #{job}" }
every(1.hour, 'Dummy job')

conflicts and exception occures. this is backtrace:

/Users/juno/.rvm/gems/ruby-1.9.2-p180@clockworkapp/gems/clockwork-0.2.3/lib/clockwork.rb:85:in `log'
/Users/juno/.rvm/gems/ruby-1.9.2-p180@clockworkapp/gems/railties-3.0.9/lib/rails/application/bootstrap.rb:29:in `block in <module:Bootstrap>'
/Users/juno/.rvm/gems/ruby-1.9.2-p180@clockworkapp/gems/railties-3.0.9/lib/rails/initializable.rb:25:in `instance_exec'
/Users/juno/.rvm/gems/ruby-1.9.2-p180@clockworkapp/gems/railties-3.0.9/lib/rails/initializable.rb:25:in `run'/Users/juno/.rvm/gems/ruby-1.9.2-p180@clockworkapp/gems/railties-3.0.9/lib/rails/initializable.rb:50:in `block in run_initializers'/Users/juno/.rvm/gems/ruby-1.9.2-p180@clockworkapp/gems/railties-3.0.9/lib/rails/initializable.rb:49:in `each'
/Users/juno/.rvm/gems/ruby-1.9.2-p180@clockworkapp/gems/railties-3.0.9/lib/rails/initializable.rb:49:in `run_initializers'/Users/juno/.rvm/gems/ruby-1.9.2-p180@clockworkapp/gems/railties-3.0.9/lib/rails/application.rb:134:in `initialize!'
/Users/juno/.rvm/gems/ruby-1.9.2-p180@clockworkapp/gems/railties-3.0.9/lib/rails/application.rb:77:in `method_missing'
/Users/juno/tmp/clockworkapp/config/environment.rb:5:in `<top (required)>'
/Users/juno/tmp/clockworkapp/clock.rb:2:in `require_relative'
/Users/juno/tmp/clockworkapp/clock.rb:2:in `<top (required)>'
/Users/juno/.rvm/gems/ruby-1.9.2-p180@clockworkapp/gems/clockwork-0.2.3/bin/clockwork:13:in `require'/Users/juno/.rvm/gems/ruby-1.9.2-p180@clockworkapp/gems/clockwork-0.2.3/bin/clockwork:13:in `<top (required)>'
/Users/juno/.rvm/gems/ruby-1.9.2-p180@clockworkapp/bin/clockwork:19:in `load'
/Users/juno/.rvm/gems/ruby-1.9.2-p180@clockworkapp/bin/clockwork:19:in `<main>'
Rails Error: Unable to access log file. Please ensure that  exists and is chmod 0666. The log level has been raised to WARN and the output directed to STDERR until the problem is fixed.

I solved this problems with renaming Clockwork::log.

--- clockwork.rb.orig   2011-06-29 17:59:38.000000000 +0900
+++ clockwork.rb    2011-06-29 18:00:08.000000000 +0900
@@ -75,14 +75,14 @@
    end

    def run
-       log "Starting clock for #{@@events.size} events: [ " + @@events.map { |e| e.to_s }.join(' ') + " ]"
+       log2 "Starting clock for #{@@events.size} events: [ " + @@events.map { |e| e.to_s }.join(' ') + " ]"
        loop do
            tick
            sleep 1
        end
    end

-   def log(msg)
+   def log2(msg)
        puts msg
    end

@@ -92,7 +92,7 @@
        end

        to_run.each do |event|
-           log "Triggering #{event}"
+           log2 "Triggering #{event}"
            event.run(t)
        end

Hope this helps.

lexer commented 13 years ago

Any updates for this issue?

lukaskonarovsky commented 13 years ago

Another solution may be inserting directly jobs into DJ database table and thus not need to load whole Rails env.

Example for postgres:

# clock.rb
require 'pg'
require 'yaml'
db = YAML.load_file(File.dirname(__FILE__) + "/database.yml")[ENV['RAILS_ENV'] || "development"]
conn = PGconn.connect(db['host'], nil, nil, nil, db['database'], db['username'], db['password'])

require 'clockwork'
include Clockwork

handler do |job|
  db_time = Time.now.utc.strftime("%Y-%m-%d %H:%M:%S")
  handler = "--- !ruby/object:ScheduledJob \njob: #{job}\n"
  conn.exec("INSERT INTO \"delayed_jobs\" (\"failed_at\", \"locked_by\", \"created_at\", \"handler\", \"updated_at\", \"priority\", \"run_at\", \"attempts\", \"locked_at\", \"last_error\") VALUES(NULL, NULL, '#{db_time}', '#{handler}', '#{db_time}', 0, '#{db_time}', 0, NULL, NULL)")
end

every(30.minutes, 'reactivate_paid_accounts')
nevinera commented 13 years ago

If anybody else is having issues with this, I have a simpler solution for you:

# lib/tasks/clock.rake

task "clock" => :environment do
  STDERR.sync = STDOUT.sync = true
  require 'clockwork'   #notice: not including, just requiring

  Clockwork.every 5.seconds, 'do-some-task' do
    puts "TEST - 5 seconds have passed"
  end

  Clockwork.run
end

Now instead of adding clockwork clock.rb to your procfile in some form, you add rake clock. This avoids the namespacing collision and keeps you from having to reload your rails environment every tick.