delayed_job_active_record 4.0.0.beta1 → 4.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
@@ -15,5 +15,5 @@ Gem::Specification.new do |spec|
15
15
  spec.require_paths = ['lib']
16
16
  spec.summary = 'ActiveRecord backend for DelayedJob'
17
17
  spec.test_files = Dir.glob("spec/**/*")
18
- spec.version = '4.0.0.beta1'
18
+ spec.version = '4.0.0.beta2'
19
19
  end
@@ -37,44 +37,38 @@ module Delayed
37
37
 
38
38
  def self.reserve(worker, max_run_time = Worker.max_run_time)
39
39
  # scope to filter to records that are "ready to run"
40
- readyScope = self.ready_to_run(worker.name, max_run_time)
40
+ ready_scope = self.ready_to_run(worker.name, max_run_time)
41
41
 
42
42
  # scope to filter to the single next eligible job
43
- readyScope = readyScope.where('priority >= ?', Worker.min_priority) if Worker.min_priority
44
- readyScope = readyScope.where('priority <= ?', Worker.max_priority) if Worker.max_priority
45
- readyScope = readyScope.where(:queue => Worker.queues) if Worker.queues.any?
46
- job = readyScope.by_priority.first
43
+ ready_scope = ready_scope.where('priority >= ?', Worker.min_priority) if Worker.min_priority
44
+ ready_scope = ready_scope.where('priority <= ?', Worker.max_priority) if Worker.max_priority
45
+ ready_scope = ready_scope.where(:queue => Worker.queues) if Worker.queues.any?
46
+ ready_scope = ready_scope.by_priority
47
47
 
48
48
  now = self.db_time_now
49
49
 
50
- return unless job
51
- job.with_lock do
52
- job.locked_at = now
53
- job.locked_by = worker.name
54
- job.save!
55
- end
56
- job
57
- end
58
-
59
- # Lock this job for this worker.
60
- # Returns true if we have the lock, false otherwise.
61
- def lock_exclusively!(max_run_time, worker)
62
- now = self.class.db_time_now
63
- affected_rows = if locked_by != worker
64
- # We don't own this job so we will update the locked_by name and the locked_at
65
- self.class.update_all(["locked_at = ?, locked_by = ?", now, worker], ["id = ? and (locked_at is null or locked_at < ?) and (run_at <= ?)", id, (now - max_run_time.to_i), now])
66
- else
67
- # We already own this job, this may happen if the job queue crashes.
68
- # Simply resume and update the locked_at
69
- self.class.update_all(["locked_at = ?", now], ["id = ? and locked_by = ?", id, worker])
70
- end
71
- if affected_rows == 1
72
- self.locked_at = now
73
- self.locked_by = worker
74
- self.changed_attributes.clear
75
- return true
50
+ # Optimizations for faster lookups on some common databases
51
+ case self.connection.adapter_name
52
+ when "PostgreSQL"
53
+ # Custom SQL required for PostgreSQL because postgres does not support UPDATE...LIMIT
54
+ # This locks the single record 'FOR UPDATE' in the subquery (http://www.postgresql.org/docs/9.0/static/sql-select.html#SQL-FOR-UPDATE-SHARE)
55
+ # Note: active_record would attempt to generate UPDATE...LIMIT like sql for postgres if we use a .limit() filter, but it would not use
56
+ # 'FOR UPDATE' and we would have many locking conflicts
57
+ quoted_table_name = self.connection.quote_table_name(self.table_name)
58
+ subquery_sql = ready_scope.limit(1).lock(true).select('id').to_sql
59
+ reserved = self.find_by_sql(["UPDATE #{quoted_table_name} SET locked_at = ?, locked_by = ? WHERE id IN (#{subquery_sql}) RETURNING *", now, worker.name])
60
+ reserved[0]
61
+ when "MySQL", "Mysql2"
62
+ # This works on MySQL and possibly some other DBs that support UPDATE...LIMIT. It uses separate queries to lock and return the job
63
+ count = ready_scope.limit(1).update_all(:locked_at => now, :locked_by => worker.name)
64
+ return nil if count == 0
65
+ self.where(:locked_at => now, :locked_by => worker.name).first
76
66
  else
77
- return false
67
+ # This is our old fashion, tried and true, but slower lookup
68
+ ready_scope.limit(worker.read_ahead).detect do |job|
69
+ count = ready_scope.where(:id => job.id).update_all(:locked_at => now, :locked_by => worker.name)
70
+ count == 1 && job.reload
71
+ end
78
72
  end
79
73
  end
80
74
 
@@ -1,17 +1,20 @@
1
1
  require 'generators/delayed_job/delayed_job_generator'
2
2
  require 'rails/generators/migration'
3
- require 'rails/generators/active_record/migration'
3
+ require 'rails/generators/active_record'
4
4
 
5
5
  # Extend the DelayedJobGenerator so that it creates an AR migration
6
6
  module DelayedJob
7
7
  class ActiveRecordGenerator < ::DelayedJobGenerator
8
8
  include Rails::Generators::Migration
9
- extend ActiveRecord::Generators::Migration
10
9
 
11
10
  self.source_paths << File.join(File.dirname(__FILE__), 'templates')
12
11
 
13
12
  def create_migration_file
14
13
  migration_template 'migration.rb', 'db/migrate/create_delayed_jobs.rb'
15
14
  end
15
+
16
+ def self.next_migration_number dirname
17
+ ActiveRecord::Generators::Base.next_migration_number dirname
18
+ end
16
19
  end
17
20
  end
@@ -1,17 +1,20 @@
1
1
  require 'generators/delayed_job/delayed_job_generator'
2
2
  require 'rails/generators/migration'
3
- require 'rails/generators/active_record/migration'
3
+ require 'rails/generators/active_record'
4
4
 
5
5
  # Extend the DelayedJobGenerator so that it creates an AR migration
6
6
  module DelayedJob
7
7
  class UpgradeGenerator < ::DelayedJobGenerator
8
8
  include Rails::Generators::Migration
9
- extend ActiveRecord::Generators::Migration
10
9
 
11
10
  self.source_paths << File.join(File.dirname(__FILE__), 'templates')
12
11
 
13
12
  def create_migration_file
14
13
  migration_template 'upgrade_migration.rb', 'db/migrate/add_queue_to_delayed_jobs.rb'
15
14
  end
15
+
16
+ def self.next_migration_number dirname
17
+ ActiveRecord::Generators::Base.next_migration_number dirname
18
+ end
16
19
  end
17
20
  end
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: 4.0.0.beta1
4
+ version: 4.0.0.beta2
5
5
  prerelease: 6
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: 2013-03-02 00:00:00.000000000 Z
14
+ date: 2013-04-02 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: activerecord
@@ -91,7 +91,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
91
91
  version: '0'
92
92
  segments:
93
93
  - 0
94
- hash: 3791598084815033964
94
+ hash: 1966467636289984878
95
95
  required_rubygems_version: !ruby/object:Gem::Requirement
96
96
  none: false
97
97
  requirements: