Code Monkey home page Code Monkey logo

delayed_job's Introduction

Delayed::Job

Delayed_job (or DJ) encapsulates the common pattern of asynchronously executing longer tasks in the background.

It is a direct extraction from Shopify where the job table is responsible for a multitude of core tasks. Amongst those tasks are:

  • sending massive newsletters
  • image resizing
  • http downloads
  • updating smart collections
  • updating solr, our search server, after product changes
  • batch imports
  • spam checks

Setup

The library evolves around a delayed_jobs table which can be created by using:


  script/generate delayed_job

The created table looks as follows:


  create_table :delayed_jobs, :force => true do |table|
    table.integer  :priority, :default => 0      # Allows some jobs to jump to the front of the queue
    table.integer  :attempts, :default => 0      # Provides for retries, but still fail eventually.
    table.text     :handler                      # YAML-encoded string of the object that will do work
    table.string   :last_error                   # reason for last failure (See Note below)
    table.datetime :run_at                       # When to run. Could be Time.now for immediately, or sometime in the future.
    table.datetime :locked_at                    # Set when a client is working on this object
    table.datetime :failed_at                    # Set when all retries have failed (actually, by default, the record is deleted instead)
    table.string   :locked_by                    # Who is working on this object (if locked)
    table.timestamps
  end

On failure, the job is scheduled again in 5 seconds + N ** 4, where N is the number of retries.

The default MAX_ATTEMPTS is 25. After this, the job either deleted (default), or left in the database with “failed_at” set.
With the default of 25 attempts, the last retry will be 20 days later, with the last interval being almost 100 hours.

The default MAX_RUN_TIME is 4.hours. If your job takes longer than that, another computer could pick it up. It’s up to you to
make sure your job doesn’t exceed this time. You should set this to the longest time you think the job could take.

By default, it will delete failed jobs (and it always deletes successful jobs). If you want to keep failed jobs, set
Delayed::Job.destroy_failed_jobs = false. The failed jobs will be marked with non-null failed_at.

Here is an example of changing job parameters in Rails:


  # config/initializers/delayed_job_config.rb
  Delayed::Job.destroy_failed_jobs = false
  silence_warnings do
    Delayed::Job.const_set("MAX_ATTEMPTS", 3)
    Delayed::Job.const_set("MAX_RUN_TIME", 5.minutes)
  end

Note: If your error messages are long, consider changing last_error field to a :text instead of a :string (255 character limit).

Usage

Jobs are simple ruby objects with a method called perform. Any object which responds to perform can be stuffed into the jobs table.
Job objects are serialized to yaml so that they can later be resurrected by the job runner.


  class NewsletterJob < Struct.new(:text, :emails)
    def perform
      emails.each { |e| NewsletterMailer.deliver_text_to_email(text, e) }
    end    
  end  
  
  Delayed::Job.enqueue NewsletterJob.new('lorem ipsum...', Customers.find(:all).collect(&:email))

There is also a second way to get jobs in the queue: send_later.


  BatchImporter.new(Shop.find(1)).send_later(:import_massive_csv, massive_csv)

This will simply create a Delayed::PerformableMethod job in the jobs table which serializes all the parameters you pass to it. There are some special smarts for active record objects
which are stored as their text representation and loaded from the database fresh when the job is actually run later.

Running the jobs

You can invoke rake jobs:work which will start working off jobs. You can cancel the rake task with CTRL-C.

You can also run by writing a simple script/job_runner, and invoking it externally:


  #!/usr/bin/env ruby
  require File.dirname(__FILE__) + '/../config/environment'
  
  Delayed::Worker.new.start  

Workers can be running on any computer, as long as they have access to the database and their clock is in sync. You can even
run multiple workers on per computer, but you must give each one a unique name:


  3.times do |n|
    worker = Delayed::Worker.new
    worker.name = 'worker-' + n.to_s
    worker.start
  end	

Keep in mind that each worker will check the database at least every 5 seconds.

Note: The rake task will exit if the database has any network connectivity problems.

Cleaning up

You can invoke rake jobs:clear to delete all jobs in the queue.

Changes

  • 1.7.0: Added failed_at column which can optionally be set after a certain amount of failed job attempts. By default failed job attempts are destroyed after about a month.
  • 1.6.0: Renamed locked_until to locked_at. We now store when we start a given job instead of how long it will be locked by the worker. This allows us to get a reading on how long a job took to execute.
  • 1.5.0: Job runners can now be run in parallel. Two new database columns are needed: locked_until and locked_by. This allows us to use pessimistic locking instead of relying on row level locks. This enables us to run as many worker processes as we need to speed up queue processing.
  • 1.2.0: Added #send_later to Object for simpler job creation
  • 1.0.0: Initial release

delayed_job's People

Contributors

andersondias avatar brunograsselli avatar chalkers avatar defunkt avatar dhh avatar elia avatar eric avatar jbarnette avatar kch avatar lorensr avatar lukemelia avatar mocoso avatar olegshaldybin avatar technoweenie avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

delayed_job's Issues

dj and god memory leak in rails application

We have delayed_job to handle background processing in our app. God monitors the more-memory-consuming DJ workers now and then and cut them off.

This setup has been working perfectly for months with daily deploys. Now today, suddenly all the workers once they are started consumes 400+ MB memory each. There were no deploys in the last few days.

What could have gone wrong? please help. The app is running on Ruby 1.9.2 with Rails 3.0.5.

Locale not automatically set

If you set the I18n.locale to a value different from the default locale the delayed tasks will not preserve the setting and you will have to set it manually inside each task (e.g. send delayed mail).

Delayed jobs reports successful completion of job, but nothing happens.

I have a process that syncs two data sets together, triggered from a static class method. When I execute this using production settings, it reports the job as completed, but the process is not run. Strangely, things work fine in the test and dev settings with the same gems, and same code. What gives?

I am restarting the delayed jobs processes every time.

Please help. This is frustrating me to pieces.

Delayed jobs not working on module methods

I find it a bit strange that

class X
def self.method; end
end

X.send_later :method

works, but

module X
def self.method; end
end

X.send_later :method

fails. Is there any philosophical reason for this? If not, I would like to see the latter working as well. Besides, it would be great if send_later methods that will fail because the target object cannot be serialized would raise an ArgmentError.

failed_at (always) empty

Hi !
I'm running DJ plugin (installed today) in a 2.3.8 Rails app.

I set Delayed::Worker.destroy_failed_jobs = false
I created a fake task which fails, raising an Exception

When DJ processes this task, it reports the exception, stores it in "last_error" field
BUT the failed_at is always nil.
Is that the right behaviour of your nice plugin ?

Thanks,
Clément

Worker inside worker

Hello,
I am using your class to perform a task similar to this:
I own a worker and this worker called me another worker.
But every time I do this the process is locked, have you ever come across this error?

Exception in db_time_now from Time.zone.now when default_timezone is :local (ie no zone)

Delayed::Job

def self.db_time_now
  (ActiveRecord::Base.default_timezone == :utc) ? Time.now.utc : Time.zone.now
end

App is in rails 2.2.3 on ruby 1.8.7.

[apphome]/config/environments does not set config.time_zone.

error demo'd in console:

> ruby script/console 
Loading development environment (Rails 2.2.3)
>> ActiveRecord::Base.default_timezone
=> :local
>> Time.zone.now
NoMethodError: You have a nil object when you didn't expect it!
The error occurred while evaluating nil.now
        from (irb):2

Simple work-around: use Time.now instead of Time.zone.now, which works for my Rails settings, but not sure that is a general solution.

NameError (uninitialized constant Delayed::Job):

I'm getting this error when using the delayed_job 3.0.0 gem...

NameError (uninitialized constant Delayed::Job):

Everything works great when I force delayed_job, 2.1.4 in my Gemfile.

I'm using rails 3.1.1.

Thanks for a great gem!

Loading associations doesn't work if class hasn't been loaded

I ran into this problem, and, it's not a DJ problem but a YAML and Rails problem. However, since DJ makes use of YAML serializing, it is probably wise to have something like this included in DJ.

#Taken from http://blog.sbf5.com/?p=39
#Basically, when an object is deserialized and the class that was serialized
#doesn't exist, then you get back a YAML object, rather than the object you
#wanted.  The fix below will use Rails' autoloading to load the class if it's
#not already there.
YAML::Syck::Resolver.class_eval do
  def transfer_with_autoload(type, val)
    match = type.match(/object:(\w+(?:::\w+)*)/)
    match && match[1].constantize
    transfer_without_autoload(type, val)
  end
  alias_method_chain :transfer, :autoload
end

Delayed::Job.work_off not processing items in the queue in the order in which they were added

Perhaps the Delayed::Job queue is order agnostic, but I would expect it to process jobs of the same priority in the same order as they were added to the queue.

Here's a failing test that I wrote against one of my models:

def test_delayed_job
comment = Comment.create!(:body => 'This is a comment')
assert_equal 0, Delayed::Job.find(:all).size
comment.send_later(:update_attribute, :body, 'Comment the first')
comment.send_later(:update_attribute, :body, 'Comment the second')
assert_equal [2, 0], Delayed::Job.work_off
assert_equal 'Comment the second', comment.reload.body
end

Unfortunately, that test fails with the following output:

<"Comment the second"> expected but was <"Comment the first">.

The order in which the two updates are dequeued differs from the order in which the two updates were enqueued. Is this the expected behavior?

Unable to access the serialised object in my model

Hi,

for examaple: User.rb model contains "reward" method which should be called using delayed job.

def reward
puts self.inspect ==> its returning the db record not the delayed job object [handler].
end
Now the problem is how do i access the delayed job object in reward method.

Failed jobs are performed twice

Under normal conditions delayed jobs run and report results as expected:

*** Starting job worker host:Erics-MacBook.local pid:19112
About to perform job
1 jobs processed at 6.1079 j/s, 0 failed ...

However, when a job fails, it attempts to perform it a second time and displays the result as 2 errors:

*** Starting job worker host:Erics-MacBook.local pid:19103
About to perform job
About to perform job
2 jobs processed at 22.1354 j/s, 2 failed ...
About to perform job
About to perform job
2 jobs processed at 89.2026 j/s, 2 failed ...
2 jobs processed at 47.0045 j/s, 2 failed ...
About to perform job
About to perform job
2 jobs processed at 90.6083 j/s, 2 failed ...

Here is the code that performs the delayed job:

class TestJob
  def initialize
    puts "Job created"
  end

  def perform
    puts "About to perform job"
    raise "Ooops"
  end
end

Logger can be nil?

Outside the context of a rails / merb app, the Delayed::Worker.logger can be nil.

It'd be nice to have a default logger, or at least pick up the rack logger if it's in use

I can create a patch for this, if there's interest.

Delayed job gem on gemcutter

Since github doesn't support compiling gems anymore, do you have any plans to move delayed_job onto gemcutter? I'm trying to get rid of my references to github as a source, but delayed_job is one of the few stragglers left.

I can push jerryvos-delayed_job to gemcutter for my own purposes, but would prefer to just use a real delayed_job gem or a tobi- one.

I'd happily provide any assistance in doing this and/or push a gem there myself, but don't want to steal ownership of delayed_job out there (though if you ask me to push it I can and then add you as an admin of it).

Disable handle_asynchronously in test mode

If you're using handle_asynchronously, I think it's reasonable to assume that you want the delaying behaviour to be "transparent" within your app. Therefore, in test mode, the relevant methods should not actually become a delayed job.

I'm achieving this currently using:

# Disable transparent delayed_job methods in test mode
module Delayed::MessageSending
  def send_later(method, *args)
    send(method, *args)
  end
end

This has the side effect of also disabling send_later. I have mixed feelings about whether that should actually happen, as it's a more explicit call, so would be interested in thoughts on that.

Hangs on Multiple Database Connection

I've setup a second database in my rails application and reference it with 'establish_connection' in its respective Models. What's odd, is a delayed_job task will hang on these models unless I temporarily update the connection to a localhost instance of the same database

I'm also able to successfully call the Job class directly (outside of delayed_job) from within a rails console, so I know there's no issue with the database connection itself.

Any ideas on this one? It just hangs, so I'm unable to produce any logging related to the issue.

Thanks!

readme does not show how to schedule at a specific time

can someone edit the readme to add the example of setting a job to run at a specific day and time? all the examples are x.from_now but as far as I can tell there is no example of how does one schedule a job to run at say 3pm on March 25, 2011?

Paperclip works using the command 'rails server' but not using the basic Mac OS apache installation

I am using Ruby on Rails 3 on a Mac Os running 'Snow Leopard' v1.6.5. After installing 'paperclip' I discovered that running the command 'rails server' from Terminal, my RoR3 application works great with 'paperclip'. It doesn't when I use the basic installation of apache from 'Snow Leopard'. I restart apache from the 'System Preferences/Sharing' panel but in logs ('Console Messages'), I found the following:
"18/01/2011 16:50:52 org.apache.httpd[12972] [31mCould not find paperclip-2.3.8 in any of the sources[0m"

What means? How to resolve the problem? Why does it happen?!

Not an issue.

This is not really an issue not sure where else to post this. I added the functionality to pass what handler you want to run for a worker. This allows you to have multiple workers going and some looking for this handler and some looking for this handler. Just wanted to add that this is an awesome plugin. Below is the updated code.

usage

Delayed::Worker.new(:min_priority => ENV['MIN_PRIORITY'], :max_priority => ENV['MAX_PRIORITY'], :handler => handler).start

updated files

job.rb

added to set what handler to run

named_scope :with_handler, lambda {|handler|
  {:conditions => ['handler like ?',"%#{handler}%"]}
}

def self.find_available(worker_name, limit = 5, max_run_time = max_run_time, handler = nil)
#added to set what handler to run
unless handler.nil?
if min_priority
scope = self.ready_to_run(worker_name, max_run_time).with_handler(handler).min_priority.by_priority(limit)
elsif max_priority
scope = self.ready_to_run(worker_name, max_run_time).with_handler(handler).max_priority.by_priority(limit)
else
scope = self.ready_to_run(worker_name, max_run_time).with_handler(handler).by_priority(limit)
end
else
if min_priority
scope = self.ready_to_run(worker_name, max_run_time).min_priority.by_priority(limit)
elsif max_priority
scope = self.ready_to_run(worker_name, max_run_time).max_priority.by_priority(limit)
else
scope = self.ready_to_run(worker_name, max_run_time).by_priority(limit)
end
end

worker.rb

def initialize(options={})
@quiet = options[:quiet]

  #added to set what handler to run
  @handler = options[:handler]

  Delayed::Job.min_priority = options[:min_priority] if options.has_key?(:min_priority)
  Delayed::Job.max_priority = options[:max_priority] if options.has_key?(:max_priority)
end

def reserve_and_run_one_job(max_run_time = job_max_run_time)

  # We get up to 5 jobs from the db. In case we cannot get exclusive access to a job we try the next.
  # this leads to a more even distribution of jobs across the worker processes
  job = Delayed::Job.find_available(name, 5, max_run_time, @handler).detect do |job|
    if job.lock_exclusively!(max_run_time, name)
      say "* [Worker(#{name})] acquired lock on #{job.name}"
      true
    else
      say "* [Worker(#{name})] failed to acquire exclusive lock for #{job.name}", Logger::WARN
      false
    end
  end

  if job.nil?
    nil # we didn't do any work, all 5 were not lockable
  else
    job.run(max_run_time)
  end
end

  scope
end

Rails 3 deprecation - Tasks directory

The tasks directory should be moved to the lib directory. This will also work on previous versions.

DEPRECATION WARNING: Having rake tasks in PLUGIN_PATH/tasks or PLUGIN_PATH/rails/tasks is deprecated. Use to PLUGIN_PATH/lib/tasks instead.

script/delayed_job needs RAILS_ENV

As you can see, the daemon uses the wrong db credentials unless RAILS_ENV is passed in:

[root@my_server ~]# /home/deploy/my_app/script/delayed_job -e staging start
/home/deploy/rails_apps/my_app/releases/20090916055509/vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb:547:in `real_connect': Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) (Mysql::Error)
    from /home/deploy/rails_apps/my_app/releases/20090916055509/vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb:547:in `connect'
    from /home/deploy/rails_apps/my_app/releases/20090916055509/vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb:199:in `initialize'
    from /home/deploy/rails_apps/my_app/releases/20090916055509/vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb:74:in `new'
    from /home/deploy/rails_apps/my_app/releases/20090916055509/vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb:74:in `mysql_connection'
    from /home/deploy/rails_apps/my_app/releases/20090916055509/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:223:in `send'
    from /home/deploy/rails_apps/my_app/releases/20090916055509/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:223:in `new_connection'
    from /home/deploy/rails_apps/my_app/releases/20090916055509/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:245:in `checkout_new_connection'
    from /home/deploy/rails_apps/my_app/releases/20090916055509/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:188:in `checkout'
     ... 19 levels...
    from /home/deploy/my_app/config/../vendor/rails/railties/lib/initializer.rb:112:in `run'
    from /home/deploy/my_app/config/environment.rb:6
    from /home/deploy/my_app/script/delayed_job:3:in `require'
    from /home/deploy/my_app/script/delayed_job:3
[root@my_server ~]# RAILS_ENV=staging /home/deploy/my_app/script/delayed_job -e staging start
[root@my_server ~]# 

DJ expects the delayed Model to inherit from AR? (resolved -> my fault)

[sorry, this was my fault]

Hi,

the model, my jobs get their info from is stored in a couchdb instance.

The background process produces these kind of errors:

MailJob failed with ActiveRecord::RecordNotFound: Couldn't find MailReceiver with ID=b8a6908bd4fdbf4b86236f1e44ff1056 - 1 failed attempts

But sometimes the queuedelivery works with the second or third try!
I could imagine that DJ expects the MailJob model to come from AR?

Any hints are very welcome ;)
-- Frank

delayed_job start creates a new process even if one is already running

Run "script/delayed_job start" twice, two processes will get started. The oldest one has to be killed manually since the pid file gets overwritten. The start action should check and not start a new process if one is already running (pid file exists, and a process with that pid is also running).

DelayedJob class model should be named delayed_job

Hy all, I'm having a really hard time trying to create an observer for delayed_job. I want to create a job watcher that will inform the different accounts that there are tasks running on back ground.

class DelayedJobObserver < ActiveRecord::Observer
  observe Delayed::Job
  def after_destroy(job)
    job_watcher = JobWatcher.find_by_job_id job.id
    job_watcher.destroy
    true
  end
end

Whenever I try to call DelayedJobObserver.observed_class, it keeps throwing:

LoadError: Expected ~/MY_APP/vendor/plugins/delayed_job/lib/delayed_job.rb to define DelayedJob

I guess it's the model class name out of standard that is causing it. Any hints?

jobs locked but not running

Periodically, I will have jobs that should be running, but... aren't. I mean they have values in the "locked_at" and "locked_by" columns, and they are clogging up the queue, but they never finish executing.

DelaydJob SQL request are very slow

NewRelic RPM show me the DelaydJob SQL request as very slow. MySQL Slow Query Log does the same.
What exactly column should be indexed? single or multiple columns indexes?
Does anybody do an analysis?

Delayed job hangs when running work_off

Hi,

When running the delayed_job rake task, it appears that delayed_job hangs without executing any of the jobs.

The rake task executes and initializes, but as soon as it gets into the work_off method it does nothing more. There's no database activity, nor any cpu activity.

Killing the rake task does however cause the jobs to run as the process cleans up after itself, so it seems like nothing happens in the rake task until it is forcibly stopped.

Has anyone experienced anything similar? We're not running multiple databases and there are no obvious errors appearing in any log files.

Also, running Delayed::Job.work_off in the rails console works fine, so it seems to be a problem with running that command via rake...

Delayed_job returns “syntax error” for process daemon and rake task

This is basically a copy of my question here: http://stackoverflow.com/questions/5383625/delayed-job-returns-syntax-error-for-process-daemon-and-rake-task

However, it seemed appropriate to re-post the question in effort to generate some form of backlog for delayed_job.

Started to have an issue this afternoon with the delayed_job process, found that the daemons were dead and restarted them...

Roughly 40 minutes later the process died again @ 86 jobs. Tried to start the daemons again and found they quietly died immediately after I start them. Checking the log I found:

s603021@ec2-184-72-244-232:~/rails/gamestreamer/current$ tail -F log/delayed_job.log 
  SQL (0.7ms)   SET NAMES 'utf8'
  SQL (0.8ms)   SET SQL_AUTO_IS_NULL=0
*** Starting job worker delayed_job.4 host:ec2-184-72-244-232.compute-1.amazonaws.com pid:17397
  Delayed::Job Columns (1.5ms)   SHOW FIELDS FROM `delayed_jobs`
  Product Columns (1.5ms)   SHOW FIELDS FROM `products`
  Game Columns (2.4ms)   SHOW FIELDS FROM `games`
  Delayed::Job Update (12.8ms)   UPDATE `delayed_jobs` SET locked_by = null, locked_at = null WHERE (locked_by = 'delayed_job.4 host:ec2-184-72-244-232.compute-1.amazonaws.com pid:17397') 
#<ArgumentError: syntax error on line 1588, col 10: `'>

I went ahead and did some digging, a lot of people used to find the daemon gem for delayed_jobs was bugged, and the rake task still worked; this was not the case for me however:

s603021@ec2-184-72-244-232:~/rails/gamestreamer/current$ RAILS_ENV=gs1_development rake jobs:work --trace
(in /data01/home/s603021/rails/gamestreamer/releases/20110302193304)
** Invoke jobs:work (first_time)
** Invoke merb_env (first_time)
** Execute merb_env
** Invoke environment (first_time)
** Execute environment
** Execute jobs:work
*** Starting job worker host:ec2-184-72-244-232.compute-1.amazonaws.com pid:17082
rake aborted!
syntax error on line 1588, col 10: `'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/1.8/yaml.rb:133:in `load'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/1.8/yaml.rb:133:in `load'
/data01/home/s603021/rails/gamestreamer/releases/20110302193304/vendor/plugins/delayed_job/lib/delayed/job.rb:234:in `deserialize'
/data01/home/s603021/rails/gamestreamer/releases/20110302193304/vendor/plugins/delayed_job/lib/delayed/job.rb:50:in `payload_object'
/data01/home/s603021/rails/gamestreamer/releases/20110302193304/vendor/plugins/delayed_job/lib/delayed/job.rb:55:in `name'
/data01/home/s603021/rails/gamestreamer/releases/20110302193304/vendor/plugins/delayed_job/lib/delayed/job.rb:90:in `run_with_lock'
/data01/home/s603021/rails/gamestreamer/releases/20110302193304/vendor/plugins/delayed_job/lib/delayed/job.rb:159:in `reserve_and_run_one_job'
/data01/home/s603021/rails/gamestreamer/releases/20110302193304/vendor/plugins/delayed_job/lib/delayed/job.rb:158:in `each'
/data01/home/s603021/rails/gamestreamer/releases/20110302193304/vendor/plugins/delayed_job/lib/delayed/job.rb:158:in `reserve_and_run_one_job'
/data01/home/s603021/rails/gamestreamer/releases/20110302193304/vendor/plugins/delayed_job/lib/delayed/job.rb:205:in `work_off'
/data01/home/s603021/rails/gamestreamer/releases/20110302193304/vendor/plugins/delayed_job/lib/delayed/job.rb:204:in `times'
/data01/home/s603021/rails/gamestreamer/releases/20110302193304/vendor/plugins/delayed_job/lib/delayed/job.rb:204:in `work_off'
/data01/home/s603021/rails/gamestreamer/releases/20110302193304/vendor/plugins/delayed_job/lib/delayed/worker.rb:30:in `start'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/1.8/benchmark.rb:308:in `realtime'
/data01/home/s603021/rails/gamestreamer/releases/20110302193304/vendor/plugins/delayed_job/lib/delayed/worker.rb:29:in `start'
/data01/home/s603021/rails/gamestreamer/releases/20110302193304/vendor/plugins/delayed_job/lib/delayed/worker.rb:26:in `loop'
/data01/home/s603021/rails/gamestreamer/releases/20110302193304/vendor/plugins/delayed_job/lib/delayed/worker.rb:26:in `start'
/data01/home/s603021/rails/gamestreamer/releases/20110302193304/vendor/plugins/delayed_job/lib/delayed/tasks.rb:13
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:636:in `call'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:636:in `execute'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:631:in `each'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:631:in `execute'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:597:in `invoke_with_call_chain'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/1.8/monitor.rb:242:in `synchronize'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:590:in `invoke_with_call_chain'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:583:in `invoke'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2051:in `invoke_task'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2029:in `top_level'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2029:in `each'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2029:in `top_level'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2068:in `standard_exception_handling'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2023:in `top_level'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2001:in `run'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2068:in `standard_exception_handling'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:1998:in `run'
/opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/rake-0.8.7/bin/rake:31
/usr/bin/rake:19:in `load'
/usr/bin/rake:19

Now I'm simply not sure what could possibly be the problem, any advice on how to get more information(or a more verbose exception) would be awesome. If anyone can help me to solve it, that'd be unbelievable. Thanks in advance--

Job.rb File: http://pastie.org/1697465

* [JOB] failed to acquire exclusive lock for xxxx

Hi,

Maybe Im not doing something right, or there is another way to do this, but I get this LockError raised a lot when Im trying the following;

I have an after_destroy, that does a Delayed::Job.enqueue()
This works fine in the single case, but I also have a dependent destroy arrangment setup - so this hook will be called multiple times in succession.

I expected that to create multiple jobs in the table, each of which get processed one by one until the queue is empty.

Unfortunately only some get processed and other raise this LockError..

  • [JOB] failed to acquire exclusive lock for xxxx (comes from job.rb in delayed_job)

Can anyone help me out? ...

m

delayed_job dies with database connection issues

Received this in our delayed_job.log... and then the DJ process dies. My best guess so far is there was a momentary network disruption between firewalls of our app and db networks.

<ActiveRecord::StatementInvalid: Mysql::Error: MySQL server has gone away: UPDATE delayed_jobs SET locked_by = null, locked_at = null WHERE (locked_by = 'delayed_job host:myhost pid:12345') >

Would be nice if DJ had more robust connection handling... i.e. catch this issue, and retry the connection until it is successful... otherwise we have to write a script to restart DJ periodically, or detect when jobs in the queue are stale.

DelayedJob crash if it failed to write error log

Problem is described below.

  1. Server try to fetch a JSON object of user information from a remote server. However some special character (maybe utf8mb4) make JSON.parse raise a error.
  2. DelayedJob caught the error thrown above, then try to write the stack trace into last_error field of table.
  3. MySQL backend of ActiveRecord happend to be in UTF8 encoding, it throw a error.
  4. WHOLE running DelayedJob instance crashed and stopped.

I think some where need a 'begin ... rescue`

log writing failed. "\xEF" from ASCII-8BIT to UTF-8
Mysql2::Error: Incorrect string value: '\xF0\x9F\x92\x85 \xE1...' for column 'last_error' at row 1: UPDATE `delayed_jobs` SET `attempts` = 1, `last_error` = '757: unexpected token at \'{\"subscribe\":1,\"openid\":\"o6uLOt6Z3zaXfWBBcz4Z4Gz3PmP8\",\"nickname\":\" 麦小喵💅 ღ奶酪酱💋\",\"sex\":2,\"language\":\"zh_CN\",\"city\":\"\",\"province\":\"\",\"country\":\"斐 ....

Truncated YAML crashes the delayed_job daemon

We were working with some beefy jobs that silently overflowed the default TEXT columns in mysql. The truncated YAML data were unable to be loaded, and were causing the daemon to crash. It looks like incomplete error handling in the job.deserialize method to me; the second YAML.load call doesn't have a rescue block, and the main rescue block for the method doesn't catch the YAML syntax error.

No way to unit test send_later effectively

I am trying to unit test DJ with some emails that are being set to send_later. While I can check the database for the record, it seems like it would make more sense if I could:

1 - Check that DJ has it
2 - Simulate a run
3 - Check to make sure it ran as expected.

Any thoughts?

Change the canonical repository

Hi,

It seems like nothing has happened in this repository for a while and the work is being done in collectiveidea/delayed_job

Why not set the canonical repository to that one so that issues and pull requests aren't filed here? This is easily done in the settings for your repository which I've handily linked to. 😃

Cheers

NoMethodError: undefined method `destroy_failed_jobs

I just installed the gem as per ReadMe instructions ( gem in gemfile, migration perfomed)

inserted into /config/initializers/delayed_job_config.rb
Delayed::Job.destroy_failed_jobs = false
silence_warnings do
Delayed::Job.const_set("MAX_ATTEMPTS", 3)
Delayed::Job.const_set("MAX_RUN_TIME", 5.minutes)
end

added require 'delayed_job' in my /config/environment.rb

the just trying to open the console got :

.rvm/gems/ruby-1.9.2-p180@rails3/gems/activerecord-3.0.7/lib/active_record/base.rb:1009:in method_missing': undefined methoddestroy_failed_jobs=' for #Class:0x00000104bd7720 (NoMethodError)
from /Users/yves/Sites/rails/testsbga/config/initializers/delayed_job_config.rb:1

Can I introspect attempts counter?

I want to write my custom method which will do something differently when 3 attempts have been reached. I am wondering if I can access the attempts counter inside my perform method?

ActiveRecords, UUIDs and Delayed Job

I'm moving some AR models to UUID's, instead of auto incremental ID's.
Delayed Job stopped working with that kind of model.

Turns out that the AR_STRING_FORMAT regex used to find the ActiveRecord object assumes that their primary key (id) is made of digits only... which is incorrect when moving to UUID (mix of letters, digits and -).

Fixed it for myself, with the following change in performable_method.rb:

instead of:
AR_STRING_FORMAT = /^AR:([A-Z][\w:]+):(\d+)$/
use:
AR_STRING_FORMAT = /^AR:([A-Z][\w:]+):([\w-]+)$/

efficient update job query

The query, which can take several seconds:

UPDATE `delayed_jobs` SET `delayed_jobs`.`locked_at` = '2016-02-17 05:20:59', `delayed_jobs`.`locked_by` = 'host:mine pid:60282' WHERE ((run_at <= '2016-02-17 05:20:59.484088' AND (locked_at IS NULL OR locked_at < '2015-02-17 05:20:59.484102') OR locked_by = 'host:mine pid:60282') AND failed_at IS NULL) ORDER BY priority ASC, run_at ASC LIMIT 1

My indexes:

Create Table: CREATE TABLE `delayed_jobs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `priority` int(11) NOT NULL DEFAULT '0',
  `attempts` int(11) NOT NULL DEFAULT '0',
  `handler` text NOT NULL,
  `last_error` text,
  `run_at` datetime DEFAULT NULL,
  `locked_at` datetime DEFAULT NULL,
  `failed_at` datetime DEFAULT NULL,
  `locked_by` varchar(191) DEFAULT NULL,
  `queue` varchar(191) DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `delayed_jobs_priority` (`priority`,`run_at`),
  KEY `index_delayed_jobs_on_priority_and_run_at` (`priority`,`run_at`)
) ENGINE=InnoDB AUTO_INCREMENT=1154052 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED

EXPLAIN says:

+----+-------------+--------------+-------+---------------+---------+---------+------+-------+-----------------------------+  
| id | select_type | table        | type  | possible_keys | key     | key_len | ref  | rows  | Extra                       |  
+----+-------------+--------------+-------+---------------+---------+---------+------+-------+-----------------------------+  
|  1 | SIMPLE      | delayed_jobs | index | NULL          | PRIMARY | 4       | NULL | 57281 | Using where; Using filesort |  
+----+-------------+--------------+-------+---------------+---------+---------+------+-------+-----------------------------+  
1 row in set (0.00 sec) 

last_error empty

When MAX_ATTEMPTS is set to 0 and an error occurs the last_error field is not set.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.