delayed_job_active_record 4.0.2 → 4.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +16 -5
- data/delayed_job_active_record.gemspec +12 -17
- data/lib/delayed/backend/active_record.rb +104 -40
- data/lib/delayed_job_active_record.rb +3 -3
- data/lib/generators/delayed_job/active_record_generator.rb +12 -6
- data/lib/generators/delayed_job/next_migration_version.rb +2 -2
- data/lib/generators/delayed_job/templates/migration.rb +13 -13
- data/lib/generators/delayed_job/templates/upgrade_migration.rb +1 -1
- data/lib/generators/delayed_job/upgrade_generator.rb +10 -15
- metadata +8 -17
- data/Rakefile +0 -38
- data/spec/database.yml +0 -14
- data/spec/delayed/backend/active_record_spec.rb +0 -101
- data/spec/delayed/serialization/active_record_spec.rb +0 -15
- data/spec/helper.rb +0 -78
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3bdebcffb191581b743a334926d45c01184fbe0a58a906741b0f7f73118375bc
|
4
|
+
data.tar.gz: fdc7e1c5c74cd0f5beef00a61d62daaf3bf91d2ca631248a7a2a7382f3d420d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 443633226e38e35bf47be09f548b9bdc1aea188f7c74244b32d8cbbd6b18cac0fd04bffac8540f075e3cc18cd737937f7049a16cc39a363be4fea6cfc9097471
|
7
|
+
data.tar.gz: c479df41fa2326aef35d02771336c17ba5ce956aa1c006769b1a67f4282e716c161d723cfd479178f24bbc21b5fdf6183e656a867d3221cf8753d21c7b800cbd
|
data/README.md
CHANGED
@@ -1,10 +1,15 @@
|
|
1
|
+
**If you're viewing this at https://github.com/collectiveidea/delayed_job_active_record,
|
2
|
+
you're reading the documentation for the master branch.
|
3
|
+
[View documentation for the latest release
|
4
|
+
(4.1.3).](https://github.com/collectiveidea/delayed_job_active_record/tree/v4.1.3)**
|
5
|
+
|
1
6
|
# DelayedJob ActiveRecord Backend
|
2
7
|
|
3
|
-
[![Gem Version](https://
|
4
|
-
[![Build Status](https://
|
5
|
-
[![Dependency Status](https://
|
6
|
-
[![Code Climate](https://
|
7
|
-
[![Coverage Status](https://
|
8
|
+
[![Gem Version](https://img.shields.io/gem/v/delayed_job_active_record.svg)](https://rubygems.org/gems/delayed_job_active_record)
|
9
|
+
[![Build Status](https://img.shields.io/travis/collectiveidea/delayed_job_active_record.svg)](https://travis-ci.org/collectiveidea/delayed_job_active_record)
|
10
|
+
[![Dependency Status](https://img.shields.io/gemnasium/collectiveidea/delayed_job_active_record.svg)](https://gemnasium.com/collectiveidea/delayed_job_active_record)
|
11
|
+
[![Code Climate](https://img.shields.io/codeclimate/github/collectiveidea/delayed_job_active_record.svg)](https://codeclimate.com/github/collectiveidea/delayed_job_active_record)
|
12
|
+
[![Coverage Status](https://img.shields.io/coveralls/collectiveidea/delayed_job_active_record.svg)](https://coveralls.io/r/collectiveidea/delayed_job_active_record)
|
8
13
|
|
9
14
|
## Installation
|
10
15
|
|
@@ -20,6 +25,12 @@ delayed_job table.
|
|
20
25
|
rails g delayed_job:active_record
|
21
26
|
rake db:migrate
|
22
27
|
|
28
|
+
## Problems locking jobs
|
29
|
+
|
30
|
+
You can try using the legacy locking code. It is usually slower but works better for certain people.
|
31
|
+
|
32
|
+
Delayed::Backend::ActiveRecord.configuration.reserve_sql_strategy = :default_sql
|
33
|
+
|
23
34
|
## Upgrading from 2.x to 3.0.0
|
24
35
|
|
25
36
|
If you're upgrading from Delayed Job 2.x, run the upgrade generator to create a
|
@@ -1,19 +1,14 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
1
|
Gem::Specification.new do |spec|
|
4
|
-
spec.add_dependency
|
5
|
-
spec.add_dependency
|
6
|
-
spec.authors = [
|
7
|
-
spec.description =
|
8
|
-
spec.email = [
|
9
|
-
spec.files = %w[CONTRIBUTING.md LICENSE.md README.md
|
10
|
-
spec.
|
11
|
-
spec.
|
12
|
-
spec.
|
13
|
-
spec.
|
14
|
-
spec.
|
15
|
-
spec.
|
16
|
-
spec.summary = 'ActiveRecord backend for DelayedJob'
|
17
|
-
spec.test_files = Dir.glob('spec/**/*')
|
18
|
-
spec.version = '4.0.2'
|
2
|
+
spec.add_dependency "activerecord", [">= 3.0", "< 5.3"]
|
3
|
+
spec.add_dependency "delayed_job", [">= 3.0", "< 5"]
|
4
|
+
spec.authors = ["Brian Ryckbost", "Matt Griffin", "Erik Michaels-Ober"]
|
5
|
+
spec.description = "ActiveRecord backend for Delayed::Job, originally authored by Tobias Lütke"
|
6
|
+
spec.email = ["bryckbost@gmail.com", "matt@griffinonline.org", "sferik@gmail.com"]
|
7
|
+
spec.files = %w[CONTRIBUTING.md LICENSE.md README.md delayed_job_active_record.gemspec] + Dir["lib/**/*.rb"]
|
8
|
+
spec.homepage = "http://github.com/collectiveidea/delayed_job_active_record"
|
9
|
+
spec.licenses = ["MIT"]
|
10
|
+
spec.name = "delayed_job_active_record"
|
11
|
+
spec.require_paths = ["lib"]
|
12
|
+
spec.summary = "ActiveRecord backend for DelayedJob"
|
13
|
+
spec.version = "4.1.3"
|
19
14
|
end
|
@@ -1,7 +1,30 @@
|
|
1
|
-
require
|
1
|
+
require "active_record/version"
|
2
2
|
module Delayed
|
3
3
|
module Backend
|
4
4
|
module ActiveRecord
|
5
|
+
class Configuration
|
6
|
+
attr_reader :reserve_sql_strategy
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
self.reserve_sql_strategy = :optimized_sql
|
10
|
+
end
|
11
|
+
|
12
|
+
def reserve_sql_strategy=(val)
|
13
|
+
if !(val == :optimized_sql || val == :default_sql)
|
14
|
+
raise ArgumentError, "allowed values are :optimized_sql or :default_sql"
|
15
|
+
end
|
16
|
+
@reserve_sql_strategy = val
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.configuration
|
21
|
+
@configuration ||= Configuration.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.configure
|
25
|
+
yield(configuration)
|
26
|
+
end
|
27
|
+
|
5
28
|
# A job object that is persisted to the database.
|
6
29
|
# Contains the work object as a YAML field.
|
7
30
|
class Job < ::ActiveRecord::Base
|
@@ -12,7 +35,10 @@ module Delayed
|
|
12
35
|
:failed_at, :locked_at, :locked_by, :handler
|
13
36
|
end
|
14
37
|
|
15
|
-
scope :by_priority, lambda { order(
|
38
|
+
scope :by_priority, lambda { order("priority ASC, run_at ASC") }
|
39
|
+
scope :min_priority, lambda { where("priority >= ?", Worker.min_priority) if Worker.min_priority }
|
40
|
+
scope :max_priority, lambda { where("priority <= ?", Worker.max_priority) if Worker.max_priority }
|
41
|
+
scope :for_queues, lambda { |queues = Worker.queues| where(queue: queues) if Array(queues).any? }
|
16
42
|
|
17
43
|
before_save :set_default_run_at
|
18
44
|
|
@@ -24,7 +50,12 @@ module Delayed
|
|
24
50
|
set_delayed_job_table_name
|
25
51
|
|
26
52
|
def self.ready_to_run(worker_name, max_run_time)
|
27
|
-
where(
|
53
|
+
where(
|
54
|
+
"(run_at <= ? AND (locked_at IS NULL OR locked_at < ?) OR locked_by = ?) AND failed_at IS NULL",
|
55
|
+
db_time_now,
|
56
|
+
db_time_now - max_run_time,
|
57
|
+
worker_name
|
58
|
+
)
|
28
59
|
end
|
29
60
|
|
30
61
|
def self.before_fork
|
@@ -37,50 +68,41 @@ module Delayed
|
|
37
68
|
|
38
69
|
# When a worker is exiting, make sure we don't have any locked jobs.
|
39
70
|
def self.clear_locks!(worker_name)
|
40
|
-
where(:
|
71
|
+
where(locked_by: worker_name).update_all(locked_by: nil, locked_at: nil)
|
41
72
|
end
|
42
73
|
|
43
|
-
def self.reserve(worker, max_run_time = Worker.max_run_time)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
ready_scope = ready_scope.where(:queue => Worker.queues) if Worker.queues.any?
|
51
|
-
ready_scope = ready_scope.by_priority
|
74
|
+
def self.reserve(worker, max_run_time = Worker.max_run_time)
|
75
|
+
ready_scope =
|
76
|
+
ready_to_run(worker.name, max_run_time)
|
77
|
+
.min_priority
|
78
|
+
.max_priority
|
79
|
+
.for_queues
|
80
|
+
.by_priority
|
52
81
|
|
53
82
|
reserve_with_scope(ready_scope, worker, db_time_now)
|
54
83
|
end
|
55
84
|
|
56
85
|
def self.reserve_with_scope(ready_scope, worker, now)
|
86
|
+
case Delayed::Backend::ActiveRecord.configuration.reserve_sql_strategy
|
57
87
|
# Optimizations for faster lookups on some common databases
|
88
|
+
when :optimized_sql
|
89
|
+
reserve_with_scope_using_optimized_sql(ready_scope, worker, now)
|
90
|
+
# Slower but in some cases more unproblematic strategy to lookup records
|
91
|
+
# See https://github.com/collectiveidea/delayed_job_active_record/pull/89 for more details.
|
92
|
+
when :default_sql
|
93
|
+
reserve_with_scope_using_default_sql(ready_scope, worker, now)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.reserve_with_scope_using_optimized_sql(ready_scope, worker, now)
|
58
98
|
case connection.adapter_name
|
59
|
-
when
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
reserved = find_by_sql(["UPDATE #{quoted_table_name} SET locked_at = ?, locked_by = ? WHERE id IN (#{subquery_sql}) RETURNING *", now, worker.name])
|
67
|
-
reserved[0]
|
68
|
-
when 'MySQL', 'Mysql2'
|
69
|
-
# This works on MySQL and possibly some other DBs that support UPDATE...LIMIT. It uses separate queries to lock and return the job
|
70
|
-
count = ready_scope.limit(1).update_all(:locked_at => now, :locked_by => worker.name)
|
71
|
-
return nil if count == 0
|
72
|
-
where(:locked_at => now, :locked_by => worker.name, :failed_at => nil).first
|
73
|
-
when 'MSSQL', 'Teradata'
|
74
|
-
# The MSSQL driver doesn't generate a limit clause when update_all is called directly
|
75
|
-
subsubquery_sql = ready_scope.limit(1).to_sql
|
76
|
-
# select("id") doesn't generate a subquery, so force a subquery
|
77
|
-
subquery_sql = "SELECT id FROM (#{subsubquery_sql}) AS x"
|
78
|
-
quoted_table_name = connection.quote_table_name(table_name)
|
79
|
-
sql = ["UPDATE #{quoted_table_name} SET locked_at = ?, locked_by = ? WHERE id IN (#{subquery_sql})", now, worker.name]
|
80
|
-
count = connection.execute(sanitize_sql(sql))
|
81
|
-
return nil if count == 0
|
82
|
-
# MSSQL JDBC doesn't support OUTPUT INSERTED.* for returning a result set, so query locked row
|
83
|
-
where(:locked_at => now, :locked_by => worker.name, :failed_at => nil).first
|
99
|
+
when "PostgreSQL", "PostGIS"
|
100
|
+
reserve_with_scope_using_optimized_postgres(ready_scope, worker, now)
|
101
|
+
when "MySQL", "Mysql2"
|
102
|
+
reserve_with_scope_using_optimized_mysql(ready_scope, worker, now)
|
103
|
+
when "MSSQL", "Teradata"
|
104
|
+
reserve_with_scope_using_optimized_mssql(ready_scope, worker, now)
|
105
|
+
# Fallback for unknown / other DBMS
|
84
106
|
else
|
85
107
|
reserve_with_scope_using_default_sql(ready_scope, worker, now)
|
86
108
|
end
|
@@ -89,11 +111,53 @@ module Delayed
|
|
89
111
|
def self.reserve_with_scope_using_default_sql(ready_scope, worker, now)
|
90
112
|
# This is our old fashion, tried and true, but slower lookup
|
91
113
|
ready_scope.limit(worker.read_ahead).detect do |job|
|
92
|
-
count = ready_scope.where(:
|
114
|
+
count = ready_scope.where(id: job.id).update_all(locked_at: now, locked_by: worker.name)
|
93
115
|
count == 1 && job.reload
|
94
116
|
end
|
95
117
|
end
|
96
118
|
|
119
|
+
def self.reserve_with_scope_using_optimized_postgres(ready_scope, worker, now)
|
120
|
+
# Custom SQL required for PostgreSQL because postgres does not support UPDATE...LIMIT
|
121
|
+
# This locks the single record 'FOR UPDATE' in the subquery
|
122
|
+
# http://www.postgresql.org/docs/9.0/static/sql-select.html#SQL-FOR-UPDATE-SHARE
|
123
|
+
# Note: active_record would attempt to generate UPDATE...LIMIT like
|
124
|
+
# SQL for Postgres if we use a .limit() filter, but it would not
|
125
|
+
# use 'FOR UPDATE' and we would have many locking conflicts
|
126
|
+
quoted_name = connection.quote_table_name(table_name)
|
127
|
+
subquery = ready_scope.limit(1).lock(true).select("id").to_sql
|
128
|
+
sql = "UPDATE #{quoted_name} SET locked_at = ?, locked_by = ? WHERE id IN (#{subquery}) RETURNING *"
|
129
|
+
reserved = find_by_sql([sql, now, worker.name])
|
130
|
+
reserved[0]
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.reserve_with_scope_using_optimized_mysql(ready_scope, worker, now)
|
134
|
+
# Removing the millisecond precision from now(time object)
|
135
|
+
# MySQL 5.6.4 onwards millisecond precision exists, but the
|
136
|
+
# datetime object created doesn't have precision, so discarded
|
137
|
+
# while updating. But during the where clause, for mysql(>=5.6.4),
|
138
|
+
# it queries with precision as well. So removing the precision
|
139
|
+
now = now.change(usec: 0)
|
140
|
+
# This works on MySQL and possibly some other DBs that support
|
141
|
+
# UPDATE...LIMIT. It uses separate queries to lock and return the job
|
142
|
+
count = ready_scope.limit(1).update_all(locked_at: now, locked_by: worker.name)
|
143
|
+
return nil if count == 0
|
144
|
+
where(locked_at: now, locked_by: worker.name, failed_at: nil).first
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.reserve_with_scope_using_optimized_mssql(ready_scope, worker, now)
|
148
|
+
# The MSSQL driver doesn't generate a limit clause when update_all
|
149
|
+
# is called directly
|
150
|
+
subsubquery_sql = ready_scope.limit(1).to_sql
|
151
|
+
# select("id") doesn't generate a subquery, so force a subquery
|
152
|
+
subquery_sql = "SELECT id FROM (#{subsubquery_sql}) AS x"
|
153
|
+
quoted_table_name = connection.quote_table_name(table_name)
|
154
|
+
sql = "UPDATE #{quoted_table_name} SET locked_at = ?, locked_by = ? WHERE id IN (#{subquery_sql})"
|
155
|
+
count = connection.execute(sanitize_sql([sql, now, worker.name]))
|
156
|
+
return nil if count == 0
|
157
|
+
# MSSQL JDBC doesn't support OUTPUT INSERTED.* for returning a result set, so query locked row
|
158
|
+
where(locked_at: now, locked_by: worker.name, failed_at: nil).first
|
159
|
+
end
|
160
|
+
|
97
161
|
# Get the current time (GMT or local depending on DB)
|
98
162
|
# Note: This does not ping the DB to get the time, so all your clients
|
99
163
|
# must have syncronized clocks.
|
@@ -103,7 +167,7 @@ module Delayed
|
|
103
167
|
elsif ::ActiveRecord::Base.default_timezone == :utc
|
104
168
|
Time.now.utc
|
105
169
|
else
|
106
|
-
Time.now
|
170
|
+
Time.now # rubocop:disable Rails/TimeZone
|
107
171
|
end
|
108
172
|
end
|
109
173
|
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "generators/delayed_job/delayed_job_generator"
|
2
|
+
require "generators/delayed_job/next_migration_version"
|
3
|
+
require "rails/generators/migration"
|
4
|
+
require "rails/generators/active_record"
|
5
5
|
|
6
6
|
# Extend the DelayedJobGenerator so that it creates an AR migration
|
7
7
|
module DelayedJob
|
@@ -9,14 +9,20 @@ module DelayedJob
|
|
9
9
|
include Rails::Generators::Migration
|
10
10
|
extend NextMigrationVersion
|
11
11
|
|
12
|
-
source_paths << File.join(File.dirname(__FILE__),
|
12
|
+
source_paths << File.join(File.dirname(__FILE__), "templates")
|
13
13
|
|
14
14
|
def create_migration_file
|
15
|
-
migration_template
|
15
|
+
migration_template "migration.rb", "db/migrate/create_delayed_jobs.rb", migration_version: migration_version
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.next_migration_number(dirname)
|
19
19
|
ActiveRecord::Generators::Base.next_migration_number dirname
|
20
20
|
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def migration_version
|
25
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]" if ActiveRecord::VERSION::MAJOR >= 5
|
26
|
+
end
|
21
27
|
end
|
22
28
|
end
|
@@ -5,9 +5,9 @@ module DelayedJob
|
|
5
5
|
def next_migration_number(dirname)
|
6
6
|
next_migration_number = current_migration_number(dirname) + 1
|
7
7
|
if ActiveRecord::Base.timestamped_migrations
|
8
|
-
[Time.now.utc.strftime(
|
8
|
+
[Time.now.utc.strftime("%Y%m%d%H%M%S"), format("%.14d", next_migration_number)].max
|
9
9
|
else
|
10
|
-
format(
|
10
|
+
format("%.3d", next_migration_number)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -1,19 +1,19 @@
|
|
1
|
-
class CreateDelayedJobs < ActiveRecord::Migration
|
1
|
+
class CreateDelayedJobs < ActiveRecord::Migration<%= migration_version %>
|
2
2
|
def self.up
|
3
|
-
create_table :delayed_jobs, :
|
4
|
-
table.integer :priority, :
|
5
|
-
table.integer :attempts, :
|
6
|
-
table.text :handler,
|
7
|
-
table.text :last_error
|
8
|
-
table.datetime :run_at
|
9
|
-
table.datetime :locked_at
|
10
|
-
table.datetime :failed_at
|
11
|
-
table.string :locked_by
|
12
|
-
table.string :queue
|
13
|
-
table.timestamps
|
3
|
+
create_table :delayed_jobs, force: true do |table|
|
4
|
+
table.integer :priority, default: 0, null: false # Allows some jobs to jump to the front of the queue
|
5
|
+
table.integer :attempts, default: 0, null: false # Provides for retries, but still fail eventually.
|
6
|
+
table.text :handler, null: false # YAML-encoded string of the object that will do work
|
7
|
+
table.text :last_error # reason for last failure (See Note below)
|
8
|
+
table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
|
9
|
+
table.datetime :locked_at # Set when a client is working on this object
|
10
|
+
table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
|
11
|
+
table.string :locked_by # Who is working on this object (if locked)
|
12
|
+
table.string :queue # The name of the queue this job is in
|
13
|
+
table.timestamps null: true
|
14
14
|
end
|
15
15
|
|
16
|
-
add_index :delayed_jobs, [:priority, :run_at], :
|
16
|
+
add_index :delayed_jobs, [:priority, :run_at], name: "delayed_jobs_priority"
|
17
17
|
end
|
18
18
|
|
19
19
|
def self.down
|
@@ -1,22 +1,17 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "generators/delayed_job/delayed_job_generator"
|
2
|
+
require "generators/delayed_job/next_migration_version"
|
3
|
+
require "rails/generators/migration"
|
4
|
+
require "rails/generators/active_record"
|
5
5
|
|
6
6
|
# Extend the DelayedJobGenerator so that it creates an AR migration
|
7
7
|
module DelayedJob
|
8
|
-
class UpgradeGenerator <
|
9
|
-
include Rails::Generators::Migration
|
10
|
-
extend NextMigrationVersion
|
11
|
-
|
12
|
-
source_paths << File.join(File.dirname(__FILE__), 'templates')
|
13
|
-
|
8
|
+
class UpgradeGenerator < ActiveRecordGenerator
|
14
9
|
def create_migration_file
|
15
|
-
migration_template
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
migration_template(
|
11
|
+
"upgrade_migration.rb",
|
12
|
+
"db/migrate/add_queue_to_delayed_jobs.rb",
|
13
|
+
migration_version: migration_version
|
14
|
+
)
|
20
15
|
end
|
21
16
|
end
|
22
17
|
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.
|
4
|
+
version: 4.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Ryckbost
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2018-04-13 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: '3.0'
|
22
22
|
- - "<"
|
23
23
|
- !ruby/object:Gem::Version
|
24
|
-
version: '
|
24
|
+
version: '5.3'
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
27
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -31,7 +31,7 @@ dependencies:
|
|
31
31
|
version: '3.0'
|
32
32
|
- - "<"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '
|
34
|
+
version: '5.3'
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: delayed_job
|
37
37
|
requirement: !ruby/object:Gem::Requirement
|
@@ -41,7 +41,7 @@ dependencies:
|
|
41
41
|
version: '3.0'
|
42
42
|
- - "<"
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
version: '
|
44
|
+
version: '5'
|
45
45
|
type: :runtime
|
46
46
|
prerelease: false
|
47
47
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -51,7 +51,7 @@ dependencies:
|
|
51
51
|
version: '3.0'
|
52
52
|
- - "<"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '5'
|
55
55
|
description: ActiveRecord backend for Delayed::Job, originally authored by Tobias
|
56
56
|
Lütke
|
57
57
|
email:
|
@@ -65,7 +65,6 @@ files:
|
|
65
65
|
- CONTRIBUTING.md
|
66
66
|
- LICENSE.md
|
67
67
|
- README.md
|
68
|
-
- Rakefile
|
69
68
|
- delayed_job_active_record.gemspec
|
70
69
|
- lib/delayed/backend/active_record.rb
|
71
70
|
- lib/delayed_job_active_record.rb
|
@@ -74,10 +73,6 @@ files:
|
|
74
73
|
- lib/generators/delayed_job/templates/migration.rb
|
75
74
|
- lib/generators/delayed_job/templates/upgrade_migration.rb
|
76
75
|
- lib/generators/delayed_job/upgrade_generator.rb
|
77
|
-
- spec/database.yml
|
78
|
-
- spec/delayed/backend/active_record_spec.rb
|
79
|
-
- spec/delayed/serialization/active_record_spec.rb
|
80
|
-
- spec/helper.rb
|
81
76
|
homepage: http://github.com/collectiveidea/delayed_job_active_record
|
82
77
|
licenses:
|
83
78
|
- MIT
|
@@ -98,12 +93,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
93
|
version: '0'
|
99
94
|
requirements: []
|
100
95
|
rubyforge_project:
|
101
|
-
rubygems_version: 2.
|
96
|
+
rubygems_version: 2.7.6
|
102
97
|
signing_key:
|
103
98
|
specification_version: 4
|
104
99
|
summary: ActiveRecord backend for DelayedJob
|
105
|
-
test_files:
|
106
|
-
- spec/database.yml
|
107
|
-
- spec/delayed/backend/active_record_spec.rb
|
108
|
-
- spec/delayed/serialization/active_record_spec.rb
|
109
|
-
- spec/helper.rb
|
100
|
+
test_files: []
|
data/Rakefile
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
require 'bundler/gem_helper'
|
3
|
-
Bundler::GemHelper.install_tasks
|
4
|
-
|
5
|
-
require 'rspec/core/rake_task'
|
6
|
-
|
7
|
-
ADAPTERS = %w[mysql postgresql sqlite3]
|
8
|
-
|
9
|
-
ADAPTERS.each do |adapter|
|
10
|
-
desc "Run RSpec code examples for #{adapter} adapter"
|
11
|
-
RSpec::Core::RakeTask.new(adapter => "#{adapter}:adapter")
|
12
|
-
|
13
|
-
namespace adapter do
|
14
|
-
task :adapter do
|
15
|
-
ENV['ADAPTER'] = adapter
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
task :coverage do
|
21
|
-
ENV['COVERAGE'] = 'true'
|
22
|
-
end
|
23
|
-
|
24
|
-
task :adapter do
|
25
|
-
ENV['ADAPTER'] = nil
|
26
|
-
end
|
27
|
-
|
28
|
-
Rake::Task[:spec].enhance do
|
29
|
-
require 'simplecov'
|
30
|
-
require 'coveralls'
|
31
|
-
|
32
|
-
Coveralls::SimpleCov::Formatter.new.format(SimpleCov.result)
|
33
|
-
end
|
34
|
-
|
35
|
-
require 'rubocop/rake_task'
|
36
|
-
RuboCop::RakeTask.new
|
37
|
-
|
38
|
-
task :default => ([:coverage] + ADAPTERS + [:adapter] + [:rubocop])
|
data/spec/database.yml
DELETED
@@ -1,101 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
require 'delayed/backend/active_record'
|
3
|
-
|
4
|
-
describe Delayed::Backend::ActiveRecord::Job do
|
5
|
-
it_behaves_like 'a delayed_job backend'
|
6
|
-
|
7
|
-
describe "reserve_with_scope" do
|
8
|
-
let(:worker) { double(name: "worker01", read_ahead: 1) }
|
9
|
-
let(:scope) { double(limit: limit, where: double(update_all: nil)) }
|
10
|
-
let(:limit) { double(job: job) }
|
11
|
-
let(:job) { double(id: 1) }
|
12
|
-
|
13
|
-
before do
|
14
|
-
allow(Delayed::Backend::ActiveRecord::Job.connection).to receive(:adapter_name).at_least(:once).and_return(dbms)
|
15
|
-
end
|
16
|
-
|
17
|
-
context "for a dbms without a specific implementation" do
|
18
|
-
let(:dbms) { "OtherDB" }
|
19
|
-
|
20
|
-
it "uses the plain sql version" do
|
21
|
-
expect(Delayed::Backend::ActiveRecord::Job).to receive(:reserve_with_scope_using_default_sql).once
|
22
|
-
Delayed::Backend::ActiveRecord::Job.reserve_with_scope(scope, worker, Time.now)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
context 'db_time_now' do
|
28
|
-
after do
|
29
|
-
Time.zone = nil
|
30
|
-
ActiveRecord::Base.default_timezone = :local
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'returns time in current time zone if set' do
|
34
|
-
Time.zone = 'Eastern Time (US & Canada)'
|
35
|
-
expect(%(EST EDT)).to include(Delayed::Job.db_time_now.zone)
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'returns UTC time if that is the AR default' do
|
39
|
-
Time.zone = nil
|
40
|
-
ActiveRecord::Base.default_timezone = :utc
|
41
|
-
expect(Delayed::Backend::ActiveRecord::Job.db_time_now.zone).to eq 'UTC'
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'returns local time if that is the AR default' do
|
45
|
-
Time.zone = 'Central Time (US & Canada)'
|
46
|
-
ActiveRecord::Base.default_timezone = :local
|
47
|
-
expect(%w[CST CDT]).to include(Delayed::Backend::ActiveRecord::Job.db_time_now.zone)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
describe 'after_fork' do
|
52
|
-
it 'calls reconnect on the connection' do
|
53
|
-
allow(ActiveRecord::Base).to receive(:establish_connection)
|
54
|
-
Delayed::Backend::ActiveRecord::Job.after_fork
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
describe 'enqueue' do
|
59
|
-
it 'allows enqueue hook to modify job at DB level' do
|
60
|
-
later = described_class.db_time_now + 20.minutes
|
61
|
-
job = Delayed::Backend::ActiveRecord::Job.enqueue :payload_object => EnqueueJobMod.new
|
62
|
-
expect(Delayed::Backend::ActiveRecord::Job.find(job.id).run_at).to be_within(1).of(later)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
if ::ActiveRecord::VERSION::MAJOR < 4 || defined?(::ActiveRecord::MassAssignmentSecurity)
|
67
|
-
context 'ActiveRecord::Base.send(:attr_accessible, nil)' do
|
68
|
-
before do
|
69
|
-
Delayed::Backend::ActiveRecord::Job.send(:attr_accessible, nil)
|
70
|
-
end
|
71
|
-
|
72
|
-
after do
|
73
|
-
Delayed::Backend::ActiveRecord::Job.send(:attr_accessible, *Delayed::Backend::ActiveRecord::Job.new.attributes.keys)
|
74
|
-
end
|
75
|
-
|
76
|
-
it 'is still accessible' do
|
77
|
-
job = Delayed::Backend::ActiveRecord::Job.enqueue :payload_object => EnqueueJobMod.new
|
78
|
-
expect(Delayed::Backend::ActiveRecord::Job.find(job.id).handler).to_not be_blank
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
context 'ActiveRecord::Base.table_name_prefix' do
|
84
|
-
it "when prefix is not set, use 'delayed_jobs' as table name" do
|
85
|
-
::ActiveRecord::Base.table_name_prefix = nil
|
86
|
-
Delayed::Backend::ActiveRecord::Job.set_delayed_job_table_name
|
87
|
-
|
88
|
-
expect(Delayed::Backend::ActiveRecord::Job.table_name).to eq 'delayed_jobs'
|
89
|
-
end
|
90
|
-
|
91
|
-
it 'when prefix is set, prepend it before default table name' do
|
92
|
-
::ActiveRecord::Base.table_name_prefix = 'custom_'
|
93
|
-
Delayed::Backend::ActiveRecord::Job.set_delayed_job_table_name
|
94
|
-
|
95
|
-
expect(Delayed::Backend::ActiveRecord::Job.table_name).to eq 'custom_delayed_jobs'
|
96
|
-
|
97
|
-
::ActiveRecord::Base.table_name_prefix = nil
|
98
|
-
Delayed::Backend::ActiveRecord::Job.set_delayed_job_table_name
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
describe ActiveRecord do
|
4
|
-
it 'loads classes with non-default primary key' do
|
5
|
-
expect do
|
6
|
-
YAML.load(Story.create.to_yaml)
|
7
|
-
end.not_to raise_error
|
8
|
-
end
|
9
|
-
|
10
|
-
it 'loads classes even if not in default scope' do
|
11
|
-
expect do
|
12
|
-
YAML.load(Story.create(:scoped => false).to_yaml)
|
13
|
-
end.not_to raise_error
|
14
|
-
end
|
15
|
-
end
|
data/spec/helper.rb
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
require 'simplecov'
|
2
|
-
require 'coveralls'
|
3
|
-
|
4
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
5
|
-
SimpleCov::Formatter::HTMLFormatter,
|
6
|
-
Coveralls::SimpleCov::Formatter
|
7
|
-
]
|
8
|
-
|
9
|
-
SimpleCov.start do
|
10
|
-
add_filter '/spec/'
|
11
|
-
minimum_coverage(73.33)
|
12
|
-
end
|
13
|
-
|
14
|
-
require 'logger'
|
15
|
-
require 'rspec'
|
16
|
-
|
17
|
-
begin
|
18
|
-
require 'protected_attributes'
|
19
|
-
rescue LoadError # rubocop:disable HandleExceptions
|
20
|
-
end
|
21
|
-
require 'delayed_job_active_record'
|
22
|
-
require 'delayed/backend/shared_spec'
|
23
|
-
|
24
|
-
Delayed::Worker.logger = Logger.new('/tmp/dj.log')
|
25
|
-
ENV['RAILS_ENV'] = 'test'
|
26
|
-
|
27
|
-
db_adapter, gemfile = ENV['ADAPTER'], ENV['BUNDLE_GEMFILE']
|
28
|
-
db_adapter ||= gemfile && gemfile[%r{gemfiles/(.*?)/}] && $1 # rubocop:disable PerlBackrefs
|
29
|
-
db_adapter ||= 'sqlite3'
|
30
|
-
|
31
|
-
config = YAML.load(File.read('spec/database.yml'))
|
32
|
-
ActiveRecord::Base.establish_connection config[db_adapter]
|
33
|
-
ActiveRecord::Base.logger = Delayed::Worker.logger
|
34
|
-
ActiveRecord::Migration.verbose = false
|
35
|
-
|
36
|
-
ActiveRecord::Schema.define do
|
37
|
-
create_table :delayed_jobs, :force => true do |table|
|
38
|
-
table.integer :priority, :default => 0
|
39
|
-
table.integer :attempts, :default => 0
|
40
|
-
table.text :handler
|
41
|
-
table.text :last_error
|
42
|
-
table.datetime :run_at
|
43
|
-
table.datetime :locked_at
|
44
|
-
table.datetime :failed_at
|
45
|
-
table.string :locked_by
|
46
|
-
table.string :queue
|
47
|
-
table.timestamps
|
48
|
-
end
|
49
|
-
|
50
|
-
add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority'
|
51
|
-
|
52
|
-
create_table :stories, :primary_key => :story_id, :force => true do |table|
|
53
|
-
table.string :text
|
54
|
-
table.boolean :scoped, :default => true
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# Purely useful for test cases...
|
59
|
-
class Story < ActiveRecord::Base
|
60
|
-
if ::ActiveRecord::VERSION::MAJOR < 4 && ActiveRecord::VERSION::MINOR < 2
|
61
|
-
set_primary_key :story_id
|
62
|
-
else
|
63
|
-
self.primary_key = :story_id
|
64
|
-
end
|
65
|
-
def tell
|
66
|
-
text
|
67
|
-
end
|
68
|
-
|
69
|
-
def whatever(n, _)
|
70
|
-
tell * n
|
71
|
-
end
|
72
|
-
default_scope { where(:scoped => true) }
|
73
|
-
|
74
|
-
handle_asynchronously :whatever
|
75
|
-
end
|
76
|
-
|
77
|
-
# Add this directory so the ActiveSupport autoloading works
|
78
|
-
ActiveSupport::Dependencies.autoload_paths << File.dirname(__FILE__)
|