blaxter-delayed_job 2.0.5 → 2.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.5
1
+ 2.0.6
data/lib/delayed/job.rb CHANGED
@@ -53,10 +53,9 @@ module Delayed
53
53
  Job.create(:payload_object => object, :priority => priority.to_i, :run_at => run_at)
54
54
  end
55
55
 
56
- # Find a few candidate jobs to run (in case some immediately get locked by others).
57
- # Return in random order prevent everyone trying to do same head job at once.
58
- def find_available( options = {} )
59
- limit = options[:limit] || 5
56
+ # Conditions used for find_available method. This is in a separated method to be able to override
57
+ # (or method chain it) more easy so you can customize the behaviour of your workers.
58
+ def conditions_available(options = {})
60
59
  max_run_time = options[:max_run_time] || MAX_RUN_TIME
61
60
  worker_name = options[:worker_name] || Worker::DEFAULT_WORKER_NAME
62
61
 
@@ -83,9 +82,14 @@ module Delayed
83
82
  conditions << "%#{options[:only_for]}%"
84
83
  end
85
84
  conditions.unshift(sql)
85
+ end
86
86
 
87
+ # Find a few candidate jobs to run (in case some immediately get locked by others).
88
+ # Return in random order prevent everyone trying to do same head job at once.
89
+ def find_available(options = {})
90
+ limit = options[:limit] || 5
87
91
  ActiveRecord::Base.silence do
88
- find(:all, :conditions => conditions, :order => NextTaskOrder, :limit => limit)
92
+ find :all, :conditions => conditions_available(options), :order => NextTaskOrder, :limit => limit
89
93
  end
90
94
  end
91
95
 
@@ -44,11 +44,12 @@ module Delayed
44
44
  # - job_types: constraint for selecting what jobs to execute (String or Array)
45
45
  def initialize(options={})
46
46
  [ :quiet, :name, :min_priority, :max_priority, :job_types, :only_for ].each do |attr_name|
47
- send "#{attr_name}=", options[attr_name]
47
+ send "#{attr_name}=", options.delete(attr_name)
48
48
  end
49
49
  # Default values
50
50
  self.name = DEFAULT_WORKER_NAME if self.name.nil?
51
51
  self.quiet = true if self.quiet.nil?
52
+ @options = options
52
53
  end
53
54
 
54
55
  def start
@@ -61,7 +62,7 @@ module Delayed
61
62
  result = nil
62
63
 
63
64
  realtime = Benchmark.realtime do
64
- result = Job.work_off( constraints )
65
+ result = Job.work_off constraints.merge(@options)
65
66
  end
66
67
 
67
68
  count = result.sum
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 2
7
7
  - 0
8
- - 5
9
- version: 2.0.5
8
+ - 6
9
+ version: 2.0.6
10
10
  platform: ruby
11
11
  authors:
12
12
  - "Tobias L\xC3\xBCtke"
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-04-22 00:00:00 +02:00
18
+ date: 2010-05-03 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -28,12 +28,8 @@ extensions: []
28
28
  extra_rdoc_files: []
29
29
 
30
30
  files:
31
- - .gitignore
32
31
  - MIT-LICENSE
33
- - README.markdown
34
- - Rakefile
35
32
  - VERSION
36
- - delayed_job.gemspec
37
33
  - generators/delayed_job/delayed_job_generator.rb
38
34
  - generators/delayed_job/templates/migration.rb
39
35
  - init.rb
@@ -42,12 +38,6 @@ files:
42
38
  - lib/delayed/performable_method.rb
43
39
  - lib/delayed/worker.rb
44
40
  - lib/delayed_job.rb
45
- - spec/database.rb
46
- - spec/delayed_method_spec.rb
47
- - spec/job_spec.rb
48
- - spec/story_spec.rb
49
- - tasks/jobs.rake
50
- - tasks/tasks.rb
51
41
  has_rdoc: true
52
42
  homepage: http://github.com/blaxter/delayed_job
53
43
  licenses: []
data/.gitignore DELETED
@@ -1,2 +0,0 @@
1
- *.gem
2
- blaxter-delayed_job.gemspec
data/README.markdown DELETED
@@ -1,202 +0,0 @@
1
- Delayed::Job
2
- ============
3
-
4
- Delayed_job (or DJ) encapsulates the common pattern of asynchronously executing longer tasks in the background.
5
-
6
- It is a direct extraction from Shopify where the job table is responsible for a multitude of core tasks. Amongst those tasks are:
7
-
8
- * sending massive newsletters
9
- * image resizing
10
- * http downloads
11
- * updating smart collections
12
- * updating solr, our search server, after product changes
13
- * batch imports
14
- * spam checks
15
-
16
- What is this fork for?
17
- ----------------------
18
-
19
- My purpose with this fork is make delayed_job for flexible. That's means you can customize how your workers behave.
20
-
21
- The common use will be to have several workers running concurrently (in one process) and each one with differents constraints so they'll run different kind of jobs.
22
-
23
-
24
- Setup
25
- -----
26
-
27
- The library evolves around a delayed_jobs table which looks as follows:
28
-
29
- create_table :delayed_jobs, :force => true do |table|
30
- table.integer :priority, :default => 0 # Allows some jobs to jump to the front of the queue
31
- table.integer :attempts, :default => 0 # Provides for retries, but still fail eventually.
32
- table.text :handler # YAML-encoded string of the object that will do work
33
- table.string :job_type # Class name of the job object, for type-specific workers
34
- table.string :name # The display name, an informative field or can be use to filter jobs
35
- table.string :last_error # reason for last failure (See Note below)
36
- table.datetime :run_at # When to run. Could be Time.now for immediately, or sometime in the future.
37
- table.datetime :locked_at # Set when a client is working on this object
38
- table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
39
- table.string :locked_by # Who is working on this object (if locked)
40
- table.datetime :finished_at # Used for statiscics / monitoring
41
- table.timestamps
42
- end
43
-
44
- You can generate the migration executing:
45
-
46
- $ script/generate delayed_job
47
- exists db/migrate
48
- create db/migrate/20090807090217_create_delayed_jobs.rb
49
-
50
-
51
- On failure, the job is scheduled again in 5 seconds + N ** 4, where N is the number of retries.
52
-
53
- The default `MAX_ATTEMPTS` is 25 (jobs can override this value by responding to `:max_attempts`). 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.
54
-
55
- 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.
56
-
57
- By default, it will delete failed 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.
58
-
59
- Same thing for successful jobs. They're deleted by default and, to keep them, set `Delayed::Job.destroy_successful_jobs = false`. They will be marked with finished_at. This is useful for gathering statistics like how long jobs took between entering the queue (created_at) and being finished (finished_at).
60
-
61
- You have several named scopes for searching unfinished/finsihed/failed jobs, very useful when destroy_successful_jobs is false `Delayed::Job.unfinished`, `Delayed::Job.finsihed`, `Delayed::Job.failed`.
62
-
63
- Here is an example of changing job parameters in Rails:
64
-
65
- # config/initializers/delayed_job_config.rb
66
- Delayed::Job.destroy_failed_jobs = false
67
- Delayed::Job.destroy_successful_jobs = false
68
- silence_warnings do
69
- Delayed::Job.const_set("MAX_ATTEMPTS", 3)
70
- Delayed::Job.const_set("MAX_RUN_TIME", 5.hours)
71
-
72
- Delayed::Worker.const_set("SLEEP", 5.minutes.to_i)
73
- end
74
-
75
- Note: If your error messages are long, consider changing last_error field to a :text instead of a :string (255 character limit).
76
-
77
-
78
- Usage
79
- -----
80
-
81
- Jobs are simple ruby objects with a method called perform. Any object which responds to perform can be stuffed into the jobs table.
82
- Job objects are serialized to yaml so that they can later be resurrected by the job runner.
83
-
84
- class NewsletterJob < Struct.new(:text, :emails)
85
- def perform
86
- emails.each { |e| NewsletterMailer.deliver_text_to_email(text, e) }
87
- end
88
- end
89
-
90
- Delayed::Job.enqueue NewsletterJob.new('lorem ipsum...', Customers.find(:all).collect(&:email))
91
-
92
- There is also a second way to get jobs in the queue: send_later.
93
-
94
- BatchImporter.new(Shop.find(1)).send_later(:import_massive_csv, massive_csv)
95
-
96
- And also you can specified priority as second parameter and the time the job should execute as thrird one
97
-
98
-
99
- class FooJob
100
- def perform
101
- ...
102
- end
103
- end
104
-
105
- important_job = FooJob.new
106
- normal_job = FooJob.new
107
-
108
- # Delayed::Job.enqueue( job, priority, start_at )
109
- Delayed::Job.enqueue important_job, 100
110
- Delayed::Job.enqueue normal_job, 1, 2.hours.from_now
111
-
112
- 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.
113
-
114
-
115
- Running the jobs
116
- ----------------
117
-
118
- You can invoke `rake jobs:work` which will start working off jobs. You can cancel the rake task with `CTRL-C`.
119
-
120
- You can also run by writing a simple `script/job_runner`, and invoking it externally:
121
-
122
-
123
- require File.dirname(__FILE__) + '/../config/environment'
124
-
125
- Delayed::Worker.new.start
126
-
127
- 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.
128
-
129
-
130
- require File.dirname(__FILE__) + '/../config/environment'
131
- N = 10
132
- workers = []
133
- N.times do |n|
134
- workers << Thread.new do
135
- Delayed::Worker.new( :name => "Worker #{n}" ).start
136
- end
137
- end
138
-
139
- workers.first.join # wait until finish (signal catched)
140
-
141
- Keep in mind that each worker will check the database at least every 5 seconds.
142
-
143
- Note: The rake task will exit if the database has any network connectivity problems.
144
-
145
- If you only want to run specific types of jobs in a given worker, include them when initializing the worker:
146
-
147
- Delayed::Worker.new(:job_types => "SimpleJob").start
148
- Delayed::Worker.new(:job_types => ["SimpleJob", "NewsletterJob"]).start
149
-
150
- Also for a more specific restriction you can define in your job's classes a `display_name` method, and create workers to specific kind of jobs
151
-
152
- # 1 - The job class that does the real work
153
- class MyJob
154
- def initialize( data )
155
- @some_data = data
156
- end
157
-
158
- def perform
159
- # do the real work
160
- end
161
-
162
- def display_name
163
- "foobar #{@some_data}"
164
- end
165
- end
166
-
167
- # 2 - Enqueue jobs
168
- Delayed::Job.enqueue MyJob.new("foobar")
169
- Delayed::Job.enqueue MyJob.new("arrrr")
170
-
171
- # 3 - Create workers, one for each type of "data"
172
- Thread.new {
173
- # This worker will only perform jobs which display name is like "%foobar%"
174
- Delayed::Worker.new :name => "Worker for foobar", :only_for => "foobar"
175
- }
176
- Thread.new {
177
- Delayed::Worker.new :name => "Worker for arrr", :only_for => "arrr"
178
- }
179
-
180
-
181
- Cleaning up
182
- -----------
183
-
184
- You can invoke `rake jobs:clear` to delete all jobs in the queue.
185
-
186
- Changes
187
- -------
188
- * 2.0.4: Add `Delayed::HIDE_BACKTRACE` for showing only the first line of the errors avoiding long backtraces
189
- * 2.0.3: The only_for feature wasn't working at all
190
- * 2.0.2: Only update run_at when it's gonna be executed another time for sure (attempts < max_attempts)
191
- * 2.0.1: named_scope Delayed::Job.failed/finished/unfinished (jobs that have failed, have finished ok or still haven't been done)
192
- * 2.0.0: Contains the changes made in this fork, the ability to create workers with individual constraints without interfere to other workers
193
-
194
- * 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.
195
-
196
- * 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.
197
-
198
- * 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.
199
-
200
- * 1.2.0: Added #send_later to Object for simpler job creation
201
-
202
- * 1.0.0: Initial release
data/Rakefile DELETED
@@ -1,38 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- begin
3
- require 'jeweler'
4
-
5
- Jeweler::Tasks.new do |s|
6
- s.name = "blaxter-delayed_job"
7
- s.summary = "Database-backed asynchronous priority queue system -- Extracted from Shopify"
8
- s.email = "blaxter@gmail.com"
9
- s.homepage = "http://github.com/blaxter/delayed_job"
10
- s.description = "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."
11
- s.authors = ["Tobias Lütke", "Jesús García Sáez"]
12
-
13
- s.has_rdoc = true
14
- s.rdoc_options = ["--main", "README.textile", "--inline-source", "--line-numbers"]
15
- s.extra_rdoc_files = ["README.textile"]
16
-
17
- s.test_files = Dir['spec/**/*']
18
- end
19
-
20
- rescue LoadError
21
- puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
22
- exit 1
23
- end
24
-
25
- require 'spec/rake/spectask'
26
- Spec::Rake::SpecTask.new(:spec) do |spec|
27
- spec.libs << 'lib' << 'spec'
28
- spec.spec_files = FileList['spec/**/*_spec.rb']
29
- end
30
-
31
- Spec::Rake::SpecTask.new(:rcov) do |spec|
32
- spec.libs << 'lib' << 'spec'
33
- spec.pattern = 'spec/**/*_spec.rb'
34
- spec.rcov = true
35
- end
36
-
37
-
38
- task :default => :spec
data/delayed_job.gemspec DELETED
@@ -1,58 +0,0 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
- # -*- encoding: utf-8 -*-
5
-
6
- Gem::Specification.new do |s|
7
- s.name = %q{delayed_job}
8
- s.version = "2.0.3"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Tobias L\303\274tke"]
12
- s.date = %q{2010-03-22}
13
- s.description = %q{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.}
14
- s.email = %q{tobi@leetsoft.com}
15
- s.files = [
16
- ".gitignore",
17
- "MIT-LICENSE",
18
- "README.markdown",
19
- "Rakefile",
20
- "VERSION",
21
- "delayed_job.gemspec",
22
- "generators/delayed_job/delayed_job_generator.rb",
23
- "generators/delayed_job/templates/migration.rb",
24
- "init.rb",
25
- "lib/delayed/job.rb",
26
- "lib/delayed/message_sending.rb",
27
- "lib/delayed/performable_method.rb",
28
- "lib/delayed/worker.rb",
29
- "lib/delayed_job.rb",
30
- "spec/database.rb",
31
- "spec/delayed_method_spec.rb",
32
- "spec/job_spec.rb",
33
- "spec/story_spec.rb",
34
- "tasks/jobs.rake",
35
- "tasks/tasks.rb"
36
- ]
37
- s.homepage = %q{http://github.com/tobi/delayed_job/tree/master}
38
- s.rdoc_options = ["--main", "README.textile", "--inline-source", "--line-numbers"]
39
- s.require_paths = ["lib"]
40
- s.rubygems_version = %q{1.3.6}
41
- s.summary = %q{Database-backed asynchronous priority queue system -- Extracted from Shopify}
42
- s.test_files = [
43
- "spec/delayed_method_spec.rb",
44
- "spec/story_spec.rb",
45
- "spec/database.rb",
46
- "spec/job_spec.rb"
47
- ]
48
-
49
- if s.respond_to? :specification_version then
50
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
51
- s.specification_version = 3
52
-
53
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
54
- else
55
- end
56
- else
57
- end
58
- end
data/tasks/jobs.rake DELETED
@@ -1 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'tasks')
data/tasks/tasks.rb DELETED
@@ -1,15 +0,0 @@
1
- # Re-definitions are appended to existing tasks
2
- task :environment
3
- task :merb_env
4
-
5
- namespace :jobs do
6
- desc "Clear the delayed_job queue."
7
- task :clear => [:merb_env, :environment] do
8
- Delayed::Job.delete_all
9
- end
10
-
11
- desc "Start a delayed_job worker."
12
- task :work => [:merb_env, :environment] do
13
- Delayed::Worker.new(:min_priority => ENV['MIN_PRIORITY'], :max_priority => ENV['MAX_PRIORITY']).start
14
- end
15
- end