delayed_job_groups_mongoid 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source :rubygems
2
+
3
+ gem 'rails'
4
+ gem 'delayed_job', '2.1.1'
5
+ gem 'delayed_job_mongoid', '1.0.0'
6
+ gem 'mongoid', '2.0.0.beta.20'
7
+ gem 'bson_ext'
8
+
9
+
10
+ group :test do
11
+ gem 'rspec-rails'
12
+ gem 'sqlite3-ruby'
13
+ gem 'autotest'
14
+ gem 'autotest-fsevent'
15
+ gem 'autotest-growl'
16
+ gem 'database_cleaner'
17
+ gem 'ruby-debug'
18
+ end
data/README.markdown ADDED
@@ -0,0 +1,74 @@
1
+ delayed job groups
2
+ ==================
3
+
4
+ Adds grouping to jobs. Only 1 job in each group will be executed regardless of the number of workers.
5
+
6
+
7
+ Requires
8
+ --------
9
+
10
+ * rails 3
11
+ * Latest version of delayed_job from github - current release(v2.1.0.pre2) does not support enqueue hooks
12
+ * active_record backend - other backends aren't supported
13
+
14
+
15
+ Install
16
+ -------
17
+
18
+ # Gemfile
19
+ gem 'delayed_job_groups'
20
+
21
+ Add migration to add lock_group column
22
+
23
+ # db/migrate/xxx_add_lock_group_to_delayed_jobs
24
+ class AddLockGroupToDelayedJobs < ActiveRecord::Migration
25
+ def self.up
26
+ add_column :delayed_jobs, :lock_group, :string
27
+ end
28
+
29
+ def self.down
30
+ remove_column :delayed_jobs, :lock_group
31
+ end
32
+ end
33
+
34
+
35
+ Usage
36
+ -----
37
+
38
+ Job groups are strings. You need to specify what the job_group should be in a block. Delayed job will only perform 1 job from each group at a time.
39
+
40
+ ### Job groups for standard jobs ###
41
+
42
+ class ResizeImageJob < Struct.new(:format)
43
+ job_group{ |resize_image_job| resize_image_job.format }
44
+
45
+ def perform
46
+ resize_to format
47
+ end
48
+ end
49
+
50
+
51
+ ### Job groups when using delay() ###
52
+
53
+ class Person < ActiveRecord::Base
54
+ job_group{ |person| person.role }
55
+
56
+ def send_welcome
57
+ ...
58
+ end
59
+ end
60
+
61
+ Person.create(:role => "admin").delay.send_welcome
62
+
63
+ ### Job groups when methods are declared asynchonous ###
64
+
65
+ class Person < ActiveRecord::Base
66
+ job_group{ |person| person.role }
67
+
68
+ def send_welcome
69
+ ...
70
+ end
71
+ handle_asynchronously :send_welcome
72
+ end
73
+
74
+ Person.create(:role => "admin").send_welcome
@@ -0,0 +1,39 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile.rb, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{delayed_job_groups_mongoid}
8
+ s.version = "0.2.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["opsb"]
12
+ s.date = %q{2010-11-04}
13
+ s.description = %q{Adds job groups to delayed_job}
14
+ s.email = %q{oliver@opsb.co.uk}
15
+ s.extra_rdoc_files = [
16
+ "README.markdown"
17
+ ]
18
+ s.files = Dir.glob("lib/**/*") + %w(Gemfile delayed_job_groups_mongoid.gemspec README.markdown)
19
+ s.homepage = %q{http://github.com/opsb/delayed_job_groups}
20
+ s.rdoc_options = ["--charset=UTF-8"]
21
+ s.require_paths = ["lib"]
22
+ s.rubygems_version = %q{1.3.7}
23
+ s.summary = %q{Adds job groups to delayed_job}
24
+ s.test_files = [
25
+ "spec/delayed_job_groups_spec.rb",
26
+ "spec/spec_helper.rb"
27
+ ]
28
+
29
+ if s.respond_to? :specification_version then
30
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
31
+ s.specification_version = 3
32
+
33
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
34
+ else
35
+ end
36
+ else
37
+ end
38
+ end
39
+
@@ -0,0 +1,7 @@
1
+ module DelayedJobGroups
2
+ class Railtie < Rails::Railtie
3
+ initializer "delayed_job_groups.initialize" do |app|
4
+ require File.dirname(__FILE__) + '/delayed_job_groups/init.rb'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ require 'delayed_job'
2
+ require File.dirname(__FILE__) + '/mongoid_groups'
3
+ require File.dirname(__FILE__) + '/job_groups'
@@ -0,0 +1,29 @@
1
+ module JobGroups
2
+
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def job_group(&block)
9
+ @lock_group_factory = block
10
+ end
11
+
12
+ def has_job_groups?
13
+ !!@lock_group_factory
14
+ end
15
+
16
+ def lock_group(payload)
17
+ @lock_group_factory.call(payload)
18
+ end
19
+ end
20
+
21
+ def enqueue(job)
22
+ payload = job.payload_object
23
+ target = payload.class == ::Delayed::PerformableMethod ? payload.object : payload
24
+ if target.class.has_job_groups?
25
+ job.lock_group = target.class.lock_group(target)
26
+ job.save
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,41 @@
1
+ require 'delayed_job'
2
+
3
+
4
+ module Delayed
5
+ class Backend::Mongoid::Job
6
+ field :lock_group
7
+ scope :in_unlocked_group, lambda{ where(:lock_group.nin => self.locked_groups) }
8
+
9
+ def self.locked_groups
10
+ Delayed::Job.only(:lock_group).where(:locked_by.ne => nil).map{|grouping| grouping[:lock_group]}
11
+ end
12
+
13
+ def self.find_available(worker_name, limit = 5, max_run_time = Worker.max_run_time)
14
+ right_now = db_time_now
15
+
16
+ conditions = {:run_at => {"$lte" => right_now}, :failed_at => nil}
17
+ (conditions[:priority] ||= {})['$gte'] = Worker.min_priority.to_i if Worker.min_priority
18
+ (conditions[:priority] ||= {})['$lte'] = Worker.max_priority.to_i if Worker.max_priority
19
+
20
+
21
+ where = "this.locked_at == null || this.locked_at < #{make_date(right_now - max_run_time)}"
22
+ results = self.in_unlocked_group.where(conditions.merge(:locked_by => worker_name)).limit(-limit).order_by([['priority', 1], ['run_at', 1]]).to_a
23
+ results += self.in_unlocked_group.where(conditions.merge('$where' => where)).limit(-limit+results.size).order_by([['priority', 1], ['run_at', 1]]).to_a if results.size < limit
24
+ results
25
+ end
26
+
27
+ end
28
+ end
29
+
30
+ __END__
31
+
32
+ scope :in_unlocked_group, lambda{
33
+ delayed_jobs = self.table_name
34
+ unlocked_groups_select = "select distinct #{delayed_jobs}.lock_group from #{delayed_jobs} where #{delayed_jobs}.locked_by is not null"
35
+ where("#{delayed_jobs}.lock_group not in (#{unlocked_groups_select}) or #{delayed_jobs}.lock_group is null")
36
+ }
37
+ scope :orig_ready_to_run, scopes[:ready_to_run]
38
+ scope :ready_to_run, lambda{ |*args|
39
+ orig_ready_to_run(*args).
40
+ in_unlocked_group
41
+ }
@@ -0,0 +1,107 @@
1
+ require 'spec/spec_helper'
2
+
3
+
4
+ class GroupedJob
5
+ include Mongoid::Document
6
+ include JobGroups
7
+ field :repository
8
+
9
+ job_group{ |simple_job| simple_job.repository }
10
+
11
+ def perform
12
+ puts "running grouped job"
13
+ end
14
+ end
15
+
16
+ class SimpleJob
17
+ include Mongoid::Document
18
+ include JobGroups
19
+
20
+ def perform
21
+ puts "running simple job"
22
+ end
23
+ end
24
+
25
+ class User
26
+ include Mongoid::Document
27
+ include JobGroups
28
+
29
+ job_group{ |user| user.role }
30
+ def send_welcome_email
31
+ puts "thanking user"
32
+ end
33
+ handle_asynchronously :send_welcome_email
34
+ def expensive_operation
35
+ puts "working hard"
36
+ end
37
+ end
38
+
39
+ describe Delayed::Job do
40
+ MAX_RUN_TIME = 4000 # seconds? TBC
41
+ WORKER = 'name_of_worker'
42
+
43
+ context "a job" do
44
+ before do
45
+ Delayed::Job.enqueue GroupedJob.new(:repository => "repo1")
46
+ end
47
+
48
+ it "should have a job group" do
49
+ Delayed::Job.first.lock_group.should == "repo1"
50
+ end
51
+ end
52
+
53
+ context "with 2 jobs in the same group, one locked, one unlocked and 1 job in a different group" do
54
+ before do
55
+ group_a_job1 = GroupedJob.new(:repository => "repo1")
56
+ group_a_job2 = GroupedJob.new(:repository => "repo1")
57
+ @group_b_job1 = GroupedJob.new(:repository => "repo2")
58
+
59
+ [group_a_job1, @group_b_job1].each{ |job| Delayed::Job.enqueue job }
60
+ queued_job = Delayed::Job.enqueue group_a_job2
61
+ queued_job.lock_exclusively!(MAX_RUN_TIME, WORKER)
62
+ end
63
+
64
+ it "should find no unlocked jobs" do
65
+ Delayed::Job.find_available(WORKER, MAX_RUN_TIME).count.should == 1
66
+ end
67
+ end
68
+
69
+ context "job with no group" do
70
+ before do
71
+ Delayed::Job.enqueue SimpleJob.new
72
+ end
73
+ it "should still be queuable" do
74
+ Delayed::Job.find_available(WORKER, MAX_RUN_TIME).count.should == 1
75
+ end
76
+ end
77
+
78
+ context "with 2 jobs in the same group, from methods declared as asynchronous, one unlocked and 1 job in a different group" do
79
+ before do
80
+ 2.times do
81
+ User.create(:role => "admin").send_welcome_email
82
+ end
83
+ 1.times{ Delayed::Job.enqueue GroupedJob.new(:repository => "repo2") }
84
+ Delayed::Job.first.lock_exclusively!(MAX_RUN_TIME, WORKER)
85
+
86
+ end
87
+
88
+ it "should find no jobs that are ready to run" do
89
+ Delayed::Job.find_available(WORKER, MAX_RUN_TIME).count.should == 1
90
+ end
91
+ end
92
+
93
+ context "with 2 jobs in the same group, from delay() calls, one unlocked and 1 job in a different group" do
94
+ before do
95
+ 2.times do
96
+ User.create(:role => "admin").delay.expensive_operation
97
+ end
98
+ 1.times{ Delayed::Job.enqueue GroupedJob.new(:repository => "repo2") }
99
+ Delayed::Job.first.lock_exclusively!(MAX_RUN_TIME, WORKER)
100
+
101
+ end
102
+
103
+ it "should find no jobs that are ready to run" do
104
+ Delayed::Job.find_available(WORKER, MAX_RUN_TIME).count.should == 1
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,41 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ require 'logger'
6
+ require 'mongoid'
7
+
8
+
9
+
10
+ ENV['RAILS_ENV'] = 'test'
11
+ require 'rails'
12
+
13
+ Mongoid.configure do |config|
14
+ name = "delayed_job_groups_mongoid"
15
+ host = "localhost"
16
+ config.master = Mongo::Connection.new.db(name)
17
+ config.slaves = [
18
+ Mongo::Connection.new(host, 27017, :slave_ok => true).db(name)
19
+ ]
20
+ config.persist_in_safe_mode = false
21
+ end
22
+
23
+
24
+ require 'rspec'
25
+ require 'delayed_job'
26
+
27
+ Delayed::Worker.logger = Logger.new('/tmp/dj.log')
28
+
29
+ Delayed::Worker.backend = :mongoid
30
+
31
+
32
+ require 'delayed_job_groups/init.rb'
33
+ RSpec.configure do |config|
34
+ require 'database_cleaner'
35
+ DatabaseCleaner.strategy = :truncation
36
+ config.after(:each) do
37
+ DatabaseCleaner.clean
38
+ end
39
+ config.filter_run :focus => true
40
+ config.run_all_when_everything_filtered = true
41
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: delayed_job_groups_mongoid
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 2
10
+ version: 0.2.2
11
+ platform: ruby
12
+ authors:
13
+ - opsb
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-04 00:00:00 +00:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Adds job groups to delayed_job
23
+ email: oliver@opsb.co.uk
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README.markdown
30
+ files:
31
+ - lib/delayed_job_groups/init.rb
32
+ - lib/delayed_job_groups/job_groups.rb
33
+ - lib/delayed_job_groups/mongoid_groups.rb
34
+ - lib/delayed_job_groups.rb
35
+ - Gemfile
36
+ - delayed_job_groups_mongoid.gemspec
37
+ - README.markdown
38
+ - spec/delayed_job_groups_spec.rb
39
+ - spec/spec_helper.rb
40
+ has_rdoc: true
41
+ homepage: http://github.com/opsb/delayed_job_groups
42
+ licenses: []
43
+
44
+ post_install_message:
45
+ rdoc_options:
46
+ - --charset=UTF-8
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ hash: 3
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ hash: 3
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ requirements: []
68
+
69
+ rubyforge_project:
70
+ rubygems_version: 1.3.7
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Adds job groups to delayed_job
74
+ test_files:
75
+ - spec/delayed_job_groups_spec.rb
76
+ - spec/spec_helper.rb