delayed_job_active_record 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,14 @@
1
+ ## How to contribute
2
+
3
+ If you find what looks like a bug:
4
+
5
+ * Search the [mailing list](http://groups.google.com/group/delayed_job) to see if anyone else had the same issue.
6
+ * Check the [GitHub issue tracker](http://github.com/collectiveidea/delayed_job_active_record/issues/) to see if anyone else has reported issue.
7
+ * If you don't see anything, create an issue with information on how to reproduce it.
8
+
9
+ If you want to contribute an enhancement or a fix:
10
+
11
+ * Fork the project on github.
12
+ * Make your changes with tests.
13
+ * Commit the changes without making changes to the Rakefile or any other files that aren't related to your enhancement or fix
14
+ * Send a pull request.
@@ -1,4 +1,4 @@
1
- Copyright (c) 2005 Tobias Luetke
1
+ Copyright (c) 2005 Tobias Lütke
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # DelayedJob ActiveRecord Backend [![Build Status](http://travis-ci.org/collectiveidea/delayed_job_active_record.png)](https://travis-ci.org/collectiveidea/delayed_job_active_record) [![Dependency Status](https://gemnasium.com/collectiveidea/delayed_job_active_record.png)](https://gemnasium.com/collectiveidea/delayed_job_active_record)
1
+ # DelayedJob ActiveRecord Backend [![Build Status](https://travis-ci.org/collectiveidea/delayed_job_active_record.png)](https://travis-ci.org/collectiveidea/delayed_job_active_record) [![Dependency Status](https://gemnasium.com/collectiveidea/delayed_job_active_record.png)](https://gemnasium.com/collectiveidea/delayed_job_active_record)
2
2
 
3
3
  ## Installation
4
4
 
@@ -12,7 +12,7 @@ If you're using Rails, run the generator to create the migration for the delayed
12
12
 
13
13
  rails g delayed_job:active_record
14
14
  rake db:migrate
15
-
15
+
16
16
  ## Upgrading from 2.x to 3.0.0
17
17
 
18
18
  If you're upgrading from Delayed Job 2.x, run the upgrade generator to create a migration to add a column to your delayed_jobs table.
@@ -21,18 +21,3 @@ If you're upgrading from Delayed Job 2.x, run the upgrade generator to create a
21
21
  rake db:migrate
22
22
 
23
23
  That's it. Use [delayed_job as normal](http://github.com/collectiveidea/delayed_job).
24
-
25
- ## How to contribute
26
-
27
- If you find what looks like a bug:
28
-
29
- * Search the [mailing list](http://groups.google.com/group/delayed_job) to see if anyone else had the same issue.
30
- * Check the [GitHub issue tracker](http://github.com/collectiveidea/delayed_job_active_record/issues/) to see if anyone else has reported issue.
31
- * If you don't see anything, create an issue with information on how to reproduce it.
32
-
33
- If you want to contribute an enhancement or a fix:
34
-
35
- * Fork the project on github.
36
- * Make your changes with tests.
37
- * Commit the changes without making changes to the Rakefile or any other files that aren't related to your enhancement or fix
38
- * Send a pull request.
@@ -0,0 +1,12 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'rspec/core/rake_task'
7
+ desc 'Run the specs'
8
+ RSpec::Core::RakeTask.new do |r|
9
+ r.verbose = false
10
+ end
11
+
12
+ task :default => :spec
@@ -0,0 +1,19 @@
1
+ # coding: utf-8
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.add_dependency 'activerecord', ['>= 2.1.0', '< 4']
5
+ spec.add_dependency 'delayed_job', '~> 3.0'
6
+ spec.authors = ["Brian Ryckbost", "Matt Griffin", "Erik Michaels-Ober"]
7
+ spec.description = 'ActiveRecord backend for Delayed::Job, originally authored by Tobias Lütke'
8
+ spec.email = ['bryckbost@gmail.com', 'matt@griffinonline.org', 'sferik@gmail.com']
9
+ spec.files = %w(CONTRIBUTING.md LICENSE.md README.md Rakefile delayed_job_active_record.gemspec)
10
+ spec.files += Dir.glob("lib/**/*.rb")
11
+ spec.files += Dir.glob("spec/**/*")
12
+ spec.homepage = 'http://github.com/collectiveidea/delayed_job_active_record'
13
+ spec.licenses = ['MIT']
14
+ spec.name = 'delayed_job_active_record'
15
+ spec.require_paths = ['lib']
16
+ spec.summary = 'ActiveRecord backend for DelayedJob'
17
+ spec.test_files = Dir.glob("spec/**/*")
18
+ spec.version = '0.4.0'
19
+ end
@@ -12,26 +12,19 @@ module Delayed
12
12
 
13
13
  before_save :set_default_run_at
14
14
 
15
- def self.rails3?
16
- ::ActiveRecord::VERSION::MAJOR == 3
15
+ def self.set_delayed_job_table_name
16
+ delayed_job_table_name = "#{::ActiveRecord::Base.table_name_prefix}delayed_jobs"
17
+ self.table_name = delayed_job_table_name
17
18
  end
18
19
 
19
- delayed_job_table_name = "#{::ActiveRecord::Base.table_name_prefix}delayed_jobs"
20
+ self.set_delayed_job_table_name
20
21
 
21
- if rails3?
22
- self.table_name = delayed_job_table_name
23
- def self.ready_to_run(worker_name, max_run_time)
24
- where('(run_at <= ? AND (locked_at IS NULL OR locked_at < ?) OR locked_by = ?) AND failed_at IS NULL', db_time_now, db_time_now - max_run_time, worker_name)
25
- end
26
- def self.by_priority
27
- order('priority ASC, run_at ASC')
28
- end
29
- else
30
- set_table_name delayed_job_table_name
31
- named_scope :ready_to_run, lambda {|worker_name, max_run_time|
32
- { :conditions => ['(run_at <= ? AND (locked_at IS NULL OR locked_at < ?) OR locked_by = ?) AND failed_at IS NULL', db_time_now, db_time_now - max_run_time, worker_name] }
33
- }
34
- named_scope :by_priority, :order => 'priority ASC, run_at ASC'
22
+ def self.ready_to_run(worker_name, max_run_time)
23
+ where('(run_at <= ? AND (locked_at IS NULL OR locked_at < ?) OR locked_by = ?) AND failed_at IS NULL', db_time_now, db_time_now - max_run_time, worker_name)
24
+ end
25
+
26
+ def self.by_priority
27
+ order('priority ASC, run_at ASC')
35
28
  end
36
29
 
37
30
  def self.before_fork
@@ -47,15 +40,32 @@ module Delayed
47
40
  update_all("locked_by = null, locked_at = null", ["locked_by = ?", worker_name])
48
41
  end
49
42
 
50
- # Find a few candidate jobs to run (in case some immediately get locked by others).
51
- def self.find_available(worker_name, limit = 5, max_run_time = Worker.max_run_time)
52
- scope = self.ready_to_run(worker_name, max_run_time)
53
- scope = scope.scoped(:conditions => ['priority >= ?', Worker.min_priority]) if Worker.min_priority
54
- scope = scope.scoped(:conditions => ['priority <= ?', Worker.max_priority]) if Worker.max_priority
55
- scope = scope.scoped(:conditions => ["queue IN (?)", Worker.queues]) if Worker.queues.any?
43
+ def self.reserve(worker, max_run_time = Worker.max_run_time)
44
+ # scope to filter to records that are "ready to run"
45
+ readyScope = self.ready_to_run(worker.name, max_run_time)
46
+
47
+ # scope to filter to the single next eligible job (locking it for update http://www.postgresql.org/docs/9.0/static/sql-select.html#SQL-FOR-UPDATE-SHARE)
48
+ nextScope = readyScope.scoped
49
+ nextScope = nextScope.scoped(:conditions => ['priority >= ?', Worker.min_priority]) if Worker.min_priority
50
+ nextScope = nextScope.scoped(:conditions => ['priority <= ?', Worker.max_priority]) if Worker.max_priority
51
+ nextScope = nextScope.scoped(:conditions => ["queue IN (?)", Worker.queues]) if Worker.queues.any?
52
+ nextScope = nextScope.scoped.by_priority.limit(1).lock(true)
53
+ nextScope = nextScope.scoped.select('id')
56
54
 
57
- ::ActiveRecord::Base.silence do
58
- scope.by_priority.all(:limit => limit)
55
+ now = self.db_time_now
56
+
57
+ if ::ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
58
+ # This works on PostgreSQL and uses 1 less query, but uses SQL not supported nativly through ActiveRecord
59
+ quotedTableName = ::ActiveRecord::Base.connection.quote_column_name(self.table_name)
60
+ reserved = self.find_by_sql(["UPDATE #{quotedTableName} SET locked_at = ?, locked_by = ? WHERE id IN (#{nextScope.to_sql}) RETURNING *",now,worker.name])
61
+ return reserved[0]
62
+ else
63
+ # This works on any database and uses seperate queries to lock and return the job
64
+ # Databases like PostgreSQL and MySQL that support "SELECT .. FOR UPDATE" (ActiveRecord Pessimistic locking) don't need the second application
65
+ # of 'readyScope' but it doesn't hurt and it ensures that the job being locked still meets ready_to_run criteria.
66
+ count = readyScope.where(:id => nextScope).update_all(:locked_at => now, :locked_by => worker.name)
67
+ return nil if count == 0
68
+ return self.where(:locked_at => now, :locked_by => worker.name).first
59
69
  end
60
70
  end
61
71
 
@@ -74,8 +84,7 @@ module Delayed
74
84
  if affected_rows == 1
75
85
  self.locked_at = now
76
86
  self.locked_by = worker
77
- self.locked_at_will_change!
78
- self.locked_by_will_change!
87
+ self.changed_attributes.clear
79
88
  return true
80
89
  else
81
90
  return false
@@ -2,43 +2,44 @@ require 'spec_helper'
2
2
  require 'delayed/backend/active_record'
3
3
 
4
4
  describe Delayed::Backend::ActiveRecord::Job do
5
- after do
6
- Time.zone = nil
7
- end
8
-
9
- it_should_behave_like 'a delayed_job backend'
5
+ it_behaves_like 'a delayed_job backend'
10
6
 
11
7
  context "db_time_now" do
12
- it "should return time in current time zone if set" do
8
+ after do
9
+ Time.zone = nil
10
+ ActiveRecord::Base.default_timezone = :local
11
+ end
12
+
13
+ it "returns time in current time zone if set" do
13
14
  Time.zone = 'Eastern Time (US & Canada)'
14
- %w(EST EDT).should include(Delayed::Job.db_time_now.zone)
15
+ expect(%(EST EDT)).to include(Delayed::Job.db_time_now.zone)
15
16
  end
16
17
 
17
- it "should return UTC time if that is the AR default" do
18
+ it "returns UTC time if that is the AR default" do
18
19
  Time.zone = nil
19
20
  ActiveRecord::Base.default_timezone = :utc
20
- Delayed::Backend::ActiveRecord::Job.db_time_now.zone.should == 'UTC'
21
+ expect(Delayed::Backend::ActiveRecord::Job.db_time_now.zone).to eq 'UTC'
21
22
  end
22
23
 
23
- it "should return local time if that is the AR default" do
24
+ it "returns local time if that is the AR default" do
24
25
  Time.zone = 'Central Time (US & Canada)'
25
26
  ActiveRecord::Base.default_timezone = :local
26
- %w(CST CDT).should include(Delayed::Backend::ActiveRecord::Job.db_time_now.zone)
27
+ expect(%w(CST CDT)).to include(Delayed::Backend::ActiveRecord::Job.db_time_now.zone)
27
28
  end
28
29
  end
29
30
 
30
31
  describe "after_fork" do
31
- it "should call reconnect on the connection" do
32
+ it "calls reconnect on the connection" do
32
33
  ActiveRecord::Base.should_receive(:establish_connection)
33
34
  Delayed::Backend::ActiveRecord::Job.after_fork
34
35
  end
35
36
  end
36
37
 
37
38
  describe "enqueue" do
38
- it "should allow enqueue hook to modify job at DB level" do
39
+ it "allows enqueue hook to modify job at DB level" do
39
40
  later = described_class.db_time_now + 20.minutes
40
41
  job = Delayed::Backend::ActiveRecord::Job.enqueue :payload_object => EnqueueJobMod.new
41
- Delayed::Backend::ActiveRecord::Job.find(job.id).run_at.should be_within(1).of(later)
42
+ expect(Delayed::Backend::ActiveRecord::Job.find(job.id).run_at).to be_within(1).of(later)
42
43
  end
43
44
  end
44
45
 
@@ -51,28 +52,28 @@ describe Delayed::Backend::ActiveRecord::Job do
51
52
  Delayed::Backend::ActiveRecord::Job.send(:attr_accessible, *Delayed::Backend::ActiveRecord::Job.new.attributes.keys)
52
53
  end
53
54
 
54
- it "should still be accessible" do
55
+ it "is still accessible" do
55
56
  job = Delayed::Backend::ActiveRecord::Job.enqueue :payload_object => EnqueueJobMod.new
56
- Delayed::Backend::ActiveRecord::Job.find(job.id).handler.should_not be_blank
57
+ expect(Delayed::Backend::ActiveRecord::Job.find(job.id).handler).to_not be_blank
57
58
  end
58
59
  end
59
60
 
60
61
  context "ActiveRecord::Base.table_name_prefix" do
61
- def reload_job_class_definition
62
- # If this can be done in a more sane manner, please fix it
63
- load File.join File.dirname(__FILE__), '..', '..', '..', 'lib', 'delayed', 'backend', 'active_record.rb'
64
- end
65
-
66
- it "when prefix is not set, should use 'delayed_jobs' as table name" do
62
+ it "when prefix is not set, use 'delayed_jobs' as table name" do
67
63
  ::ActiveRecord::Base.table_name_prefix = nil
68
- reload_job_class_definition
69
- Delayed::Backend::ActiveRecord::Job.table_name.should eq 'delayed_jobs'
64
+ Delayed::Backend::ActiveRecord::Job.set_delayed_job_table_name
65
+
66
+ expect(Delayed::Backend::ActiveRecord::Job.table_name).to eq 'delayed_jobs'
70
67
  end
71
68
 
72
- it "when prefix is set, should prepend it before default table name" do
69
+ it "when prefix is set, prepend it before default table name" do
73
70
  ::ActiveRecord::Base.table_name_prefix = 'custom_'
74
- reload_job_class_definition
75
- Delayed::Backend::ActiveRecord::Job.table_name.should eq 'custom_delayed_jobs'
71
+ Delayed::Backend::ActiveRecord::Job.set_delayed_job_table_name
72
+
73
+ expect(Delayed::Backend::ActiveRecord::Job.table_name).to eq 'custom_delayed_jobs'
74
+
75
+ ::ActiveRecord::Base.table_name_prefix = nil
76
+ Delayed::Backend::ActiveRecord::Job.set_delayed_job_table_name
76
77
  end
77
78
  end
78
79
  end
@@ -1,15 +1,15 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ActiveRecord do
4
- it 'should load classes with non-default primary key' do
5
- lambda {
4
+ it "loads classes with non-default primary key" do
5
+ expect {
6
6
  YAML.load(Story.create.to_yaml)
7
- }.should_not raise_error
7
+ }.not_to raise_error
8
8
  end
9
9
 
10
- it 'should load classes even if not in default scope' do
11
- lambda {
10
+ it "loads classes even if not in default scope" do
11
+ expect {
12
12
  YAML.load(Story.create(:scoped => false).to_yaml)
13
- }.should_not raise_error
13
+ }.not_to raise_error
14
14
  end
15
15
  end
@@ -40,7 +40,7 @@ end
40
40
 
41
41
  # Purely useful for test cases...
42
42
  class Story < ActiveRecord::Base
43
- set_primary_key :story_id
43
+ self.primary_key = :story_id
44
44
  def tell; text; end
45
45
  def whatever(n, _); tell*n; end
46
46
  default_scope where(:scoped => true)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: delayed_job_active_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-09-30 00:00:00.000000000 Z
14
+ date: 2013-02-10 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: activerecord
@@ -51,64 +51,21 @@ dependencies:
51
51
  - - ~>
52
52
  - !ruby/object:Gem::Version
53
53
  version: '3.0'
54
- - !ruby/object:Gem::Dependency
55
- name: rake
56
- requirement: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ! '>='
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ! '>='
68
- - !ruby/object:Gem::Version
69
- version: '0'
70
- - !ruby/object:Gem::Dependency
71
- name: rspec
72
- requirement: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
77
- version: '0'
78
- type: :development
79
- prerelease: false
80
- version_requirements: !ruby/object:Gem::Requirement
81
- none: false
82
- requirements:
83
- - - ! '>='
84
- - !ruby/object:Gem::Version
85
- version: '0'
86
- - !ruby/object:Gem::Dependency
87
- name: sqlite3
88
- requirement: !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - ! '>='
92
- - !ruby/object:Gem::Version
93
- version: '0'
94
- type: :development
95
- prerelease: false
96
- version_requirements: !ruby/object:Gem::Requirement
97
- none: false
98
- requirements:
99
- - - ! '>='
100
- - !ruby/object:Gem::Version
101
- version: '0'
102
- description: ActiveRecord backend for DelayedJob, originally authored by Tobias Luetke
54
+ description: ActiveRecord backend for Delayed::Job, originally authored by Tobias
55
+ Lütke
103
56
  email:
104
57
  - bryckbost@gmail.com
105
58
  - matt@griffinonline.org
106
59
  - sferik@gmail.com
107
60
  executables: []
108
61
  extensions: []
109
- extra_rdoc_files:
110
- - README.md
62
+ extra_rdoc_files: []
111
63
  files:
64
+ - CONTRIBUTING.md
65
+ - LICENSE.md
66
+ - README.md
67
+ - Rakefile
68
+ - delayed_job_active_record.gemspec
112
69
  - lib/delayed/backend/active_record.rb
113
70
  - lib/delayed_job_active_record.rb
114
71
  - lib/generators/delayed_job/active_record_generator.rb
@@ -119,16 +76,11 @@ files:
119
76
  - spec/delayed/backend/active_record_spec.rb
120
77
  - spec/delayed/serialization/active_record_spec.rb
121
78
  - spec/spec_helper.rb
122
- - LICENSE
123
- - README.md
124
79
  homepage: http://github.com/collectiveidea/delayed_job_active_record
125
- licenses: []
80
+ licenses:
81
+ - MIT
126
82
  post_install_message:
127
- rdoc_options:
128
- - --main
129
- - README.md
130
- - --inline-source
131
- - --line-numbers
83
+ rdoc_options: []
132
84
  require_paths:
133
85
  - lib
134
86
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -139,7 +91,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
139
91
  version: '0'
140
92
  segments:
141
93
  - 0
142
- hash: -4543581460881455669
94
+ hash: -1678145937006917333
143
95
  required_rubygems_version: !ruby/object:Gem::Requirement
144
96
  none: false
145
97
  requirements:
@@ -148,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
148
100
  version: '0'
149
101
  segments:
150
102
  - 0
151
- hash: -4543581460881455669
103
+ hash: -1678145937006917333
152
104
  requirements: []
153
105
  rubyforge_project:
154
106
  rubygems_version: 1.8.23