delayed_job_heartbeat_plugin 0.1.0 → 0.5.0
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.
- checksums.yaml +5 -5
- data/.circleci/config.yml +93 -0
- data/.github/CODEOWNERS +1 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +8 -0
- data/Appraisals +16 -0
- data/CHANGELOG.md +18 -0
- data/Gemfile +2 -0
- data/Rakefile +2 -0
- data/delayed_job_heartbeat_plugin.gemspec +22 -16
- data/gemfiles/rails_6.0.gemfile +8 -0
- data/gemfiles/rails_6.1.gemfile +8 -0
- data/gemfiles/rails_7.0.gemfile +8 -0
- data/lib/delayed/heartbeat/compatibility.rb +2 -0
- data/lib/delayed/heartbeat/configuration.rb +3 -1
- data/lib/delayed/heartbeat/delete_worker_results.rb +18 -26
- data/lib/delayed/heartbeat/plugin.rb +4 -5
- data/lib/delayed/heartbeat/railtie.rb +2 -0
- data/lib/delayed/heartbeat/tasks.rb +3 -1
- data/lib/delayed/heartbeat/version.rb +2 -2
- data/lib/delayed/heartbeat/worker.rb +3 -1
- data/lib/delayed/heartbeat/worker_heartbeat.rb +6 -3
- data/lib/delayed/heartbeat.rb +6 -6
- data/lib/delayed_job_heartbeat_plugin.rb +2 -0
- data/lib/generators/delayed_job_heartbeat_plugin/install_generator.rb +4 -2
- data/lib/generators/delayed_job_heartbeat_plugin/templates/{migration.rb → migration.erb} +1 -1
- data/spec/db/schema.rb +2 -0
- data/spec/delayed/heartbeat/delete_worker_results_spec.rb +13 -14
- data/spec/delayed/heartbeat/worker_heartbeat_spec.rb +2 -0
- data/spec/delayed/heartbeat_spec.rb +2 -2
- data/spec/spec_helper.rb +24 -12
- data/spec/support/destroyed_model.rb +2 -2
- data/spec/support/test_job.rb +2 -0
- data/spec/support/test_job_with_callbacks.rb +2 -0
- data/spec/support/wait.rb +2 -0
- metadata +111 -49
- data/.travis.yml +0 -14
- data/spec/db/database.yml +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5ba564b35f94921f30c324a5597705a743fd443946492b131f382282d2650c91
|
4
|
+
data.tar.gz: 63947153fbcf5b303d47981cee2a21eb8f4d76298ad6bc4e8fefe18da9cabe26
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25f9c2a073c041070f6f25d0b5c20a03fe60a598880a95f25478e62fca3d1c2cd046e312e4d7da4355254b86f3fc2b5551a8d35d287baff015dcde5a767dc727
|
7
|
+
data.tar.gz: 6abadd87e0918dc4f0cb9f501455444b8ea81e30473913d229967d95909682d1673402267fe47c20c4d134136e09592f6607648b70320fa1f6b508dc78e70bda
|
@@ -0,0 +1,93 @@
|
|
1
|
+
version: 2.1
|
2
|
+
jobs:
|
3
|
+
lint:
|
4
|
+
docker:
|
5
|
+
- image: salsify/ruby_ci:2.7.6
|
6
|
+
working_directory: ~/delayed_job_heartbeat_plugin
|
7
|
+
steps:
|
8
|
+
- checkout
|
9
|
+
- restore_cache:
|
10
|
+
keys:
|
11
|
+
- v1-gems-ruby-2.7.6-{{ checksum "delayed_job_heartbeat_plugin.gemspec" }}-{{ checksum "Gemfile" }}
|
12
|
+
- v1-gems-ruby-2.7.6-
|
13
|
+
- run:
|
14
|
+
name: Install Gems
|
15
|
+
command: |
|
16
|
+
if ! bundle check --path=vendor/bundle; then
|
17
|
+
bundle install --path=vendor/bundle --jobs=4 --retry=3
|
18
|
+
bundle clean
|
19
|
+
fi
|
20
|
+
- save_cache:
|
21
|
+
key: v1-gems-ruby-2.7.6-{{ checksum "delayed_job_heartbeat_plugin.gemspec" }}-{{ checksum "Gemfile" }}
|
22
|
+
paths:
|
23
|
+
- "vendor/bundle"
|
24
|
+
- "gemfiles/vendor/bundle"
|
25
|
+
- run:
|
26
|
+
name: Run Rubocop
|
27
|
+
command: bundle exec rubocop --config .rubocop.yml
|
28
|
+
test:
|
29
|
+
parameters:
|
30
|
+
gemfile:
|
31
|
+
type: string
|
32
|
+
ruby_version:
|
33
|
+
type: string
|
34
|
+
docker:
|
35
|
+
- image: salsify/ruby_ci:<< parameters.ruby_version >>
|
36
|
+
environment:
|
37
|
+
DB_USER: "circleci"
|
38
|
+
- image: cimg/postgres:12.7
|
39
|
+
environment:
|
40
|
+
POSTGRES_USER: "circleci"
|
41
|
+
POSTGRES_DB: "circle_test"
|
42
|
+
POSTGRES_HOST_AUTH_METHOD: "trust"
|
43
|
+
environment:
|
44
|
+
RACK_ENV: "test"
|
45
|
+
RAILS_ENV: "test"
|
46
|
+
CIRCLE_TEST_REPORTS: "test-results"
|
47
|
+
BUNDLE_GEMFILE: << parameters.gemfile >>
|
48
|
+
working_directory: ~/delayed_job_heartbeat_plugin
|
49
|
+
steps:
|
50
|
+
- checkout
|
51
|
+
- restore_cache:
|
52
|
+
keys:
|
53
|
+
- v1-gems-ruby-<< parameters.ruby_version >>-{{ checksum "delayed_job_heartbeat_plugin.gemspec" }}-{{ checksum "<< parameters.gemfile >>" }}
|
54
|
+
- v1-gems-ruby-<< parameters.ruby_version >>-
|
55
|
+
- run:
|
56
|
+
name: Install Gems
|
57
|
+
command: |
|
58
|
+
if ! bundle check --path=vendor/bundle; then
|
59
|
+
bundle install --path=vendor/bundle --jobs=4 --retry=3
|
60
|
+
bundle clean
|
61
|
+
fi
|
62
|
+
- save_cache:
|
63
|
+
key: v1-gems-ruby-<< parameters.ruby_version >>-{{ checksum "delayed_job_heartbeat_plugin.gemspec" }}-{{ checksum "<< parameters.gemfile >>" }}
|
64
|
+
paths:
|
65
|
+
- "vendor/bundle"
|
66
|
+
- "gemfiles/vendor/bundle"
|
67
|
+
- run:
|
68
|
+
name: Wait for Database
|
69
|
+
command: dockerize -wait tcp://localhost:5432 -timeout 60s
|
70
|
+
- run:
|
71
|
+
name: Wait for Database User
|
72
|
+
command: t=30; for i in `seq $t`; do psql -h localhost -p 5432 -U circleci -d circle_test -c '\q' && break; [ $i -eq $t ] && return 2; sleep 1; done;
|
73
|
+
- run:
|
74
|
+
name: Run Tests
|
75
|
+
command: |
|
76
|
+
bundle exec rspec --format RspecJunitFormatter --out $CIRCLE_TEST_REPORTS/rspec/junit.xml --format progress spec
|
77
|
+
- store_test_results:
|
78
|
+
path: "test-results"
|
79
|
+
workflows:
|
80
|
+
build:
|
81
|
+
jobs:
|
82
|
+
- lint
|
83
|
+
- test:
|
84
|
+
matrix:
|
85
|
+
parameters:
|
86
|
+
gemfile:
|
87
|
+
- "gemfiles/rails_6.0.gemfile"
|
88
|
+
- "gemfiles/rails_6.1.gemfile"
|
89
|
+
- "gemfiles/rails_7.0.gemfile"
|
90
|
+
ruby_version:
|
91
|
+
- "2.7.6"
|
92
|
+
- "3.0.4"
|
93
|
+
- "3.1.2"
|
data/.github/CODEOWNERS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* @jturkel @will89
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
data/Appraisals
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
appraise 'rails-6.0' do
|
4
|
+
gem 'activerecord', '~> 6.0.4'
|
5
|
+
gem 'activesupport', '~> 6.0.4'
|
6
|
+
end
|
7
|
+
|
8
|
+
appraise 'rails-6.1' do
|
9
|
+
gem 'activerecord', '~> 6.1.5'
|
10
|
+
gem 'activesupport', '~> 6.1.5'
|
11
|
+
end
|
12
|
+
|
13
|
+
appraise 'rails-7.0' do
|
14
|
+
gem 'activerecord', '~> 7.0.2'
|
15
|
+
gem 'activesupport', '~> 7.0.2'
|
16
|
+
end
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
### 0.5.0
|
4
|
+
- Drop support for ruby < 2.7
|
5
|
+
- Add support for ruby 3.1
|
6
|
+
- Drop Rails 5.2
|
7
|
+
- Add Rails 7.0
|
8
|
+
|
9
|
+
### 0.4.0
|
10
|
+
- Use frozen string literals.
|
11
|
+
|
12
|
+
### 0.3.0
|
13
|
+
* Drop support for Ruby < 2.5.
|
14
|
+
* Drop support for Rails < 5.2.
|
15
|
+
* Bugfix for rails version in generated migration files
|
16
|
+
|
17
|
+
### 0.2.0
|
18
|
+
* Enable correlation between workers and unlocked jobs in results returned from deleting workers
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'delayed/heartbeat/version'
|
5
6
|
|
@@ -13,27 +14,32 @@ Gem::Specification.new do |spec|
|
|
13
14
|
spec.homepage = 'https://github.com/salsify/delayed_job_heartbeat_plugin'
|
14
15
|
spec.license = 'MIT'
|
15
16
|
|
16
|
-
spec.
|
17
|
+
if spec.respond_to?(:metadata)
|
18
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
19
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
20
|
+
else
|
21
|
+
raise 'RubyGems 2.0 or newer is required to set allowed_push_host.'
|
22
|
+
end
|
23
|
+
|
24
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
25
|
spec.test_files = Dir.glob('spec/**/*')
|
18
26
|
spec.require_paths = ['lib']
|
19
27
|
|
20
|
-
spec.required_ruby_version = '>= 2.
|
28
|
+
spec.required_ruby_version = '>= 2.7'
|
21
29
|
|
22
30
|
spec.add_dependency 'delayed_job', '>= 4.1.0'
|
23
31
|
spec.add_dependency 'delayed_job_active_record', '>= 4.1.0'
|
24
32
|
|
25
|
-
spec.add_development_dependency 'activerecord',
|
26
|
-
spec.add_development_dependency '
|
33
|
+
spec.add_development_dependency 'activerecord', ['>= 5.2', '< 7.1']
|
34
|
+
spec.add_development_dependency 'appraisal'
|
35
|
+
spec.add_development_dependency 'bundler'
|
36
|
+
spec.add_development_dependency 'coveralls_reborn', '>= 0.18.0'
|
27
37
|
spec.add_development_dependency 'database_cleaner', '>= 1.2'
|
28
|
-
spec.add_development_dependency '
|
29
|
-
spec.add_development_dependency '
|
30
|
-
spec.add_development_dependency '
|
38
|
+
spec.add_development_dependency 'pg'
|
39
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
40
|
+
spec.add_development_dependency 'rspec', '~> 3'
|
41
|
+
spec.add_development_dependency 'rspec_junit_formatter'
|
42
|
+
spec.add_development_dependency 'salsify_rubocop', '~> 1.0.2'
|
43
|
+
spec.add_development_dependency 'simplecov'
|
31
44
|
spec.add_development_dependency 'timecop'
|
32
|
-
|
33
|
-
if RUBY_PLATFORM == 'java'
|
34
|
-
spec.add_development_dependency 'jdbc-sqlite3'
|
35
|
-
spec.add_development_dependency 'activerecord-jdbcsqlite3-adapter'
|
36
|
-
else
|
37
|
-
spec.add_development_dependency 'sqlite3'
|
38
|
-
end
|
39
45
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Delayed
|
2
4
|
module Heartbeat
|
3
5
|
class Configuration
|
@@ -22,7 +24,7 @@ module Delayed
|
|
22
24
|
|
23
25
|
self.heartbeat_timeout_seconds ||= 180
|
24
26
|
self.heartbeat_interval_seconds ||= 60
|
25
|
-
self.on_worker_termination ||= Proc.new {
|
27
|
+
self.on_worker_termination ||= Proc.new {}
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
@@ -1,42 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Delayed
|
2
4
|
module Heartbeat
|
3
5
|
class DeleteWorkerResults
|
4
|
-
|
6
|
+
def initialize(worker_job_map)
|
7
|
+
@worker_job_map = worker_job_map
|
8
|
+
end
|
9
|
+
|
10
|
+
def workers
|
11
|
+
@worker_job_map.keys
|
12
|
+
end
|
5
13
|
|
6
|
-
def
|
7
|
-
@
|
8
|
-
@unlocked_jobs = unlocked_jobs
|
14
|
+
def unlocked_jobs(worker = nil)
|
15
|
+
worker ? @worker_job_map.fetch(worker, []) : @worker_job_map.values.flatten
|
9
16
|
end
|
10
17
|
|
11
18
|
def empty?
|
12
|
-
|
19
|
+
@worker_job_map.empty?
|
13
20
|
end
|
14
21
|
|
15
22
|
def to_s
|
16
23
|
io = StringIO.new
|
17
24
|
workers.each do |worker|
|
18
|
-
|
25
|
+
worker_description = "#{worker.label}(#{worker.name})"
|
26
|
+
io.puts("Deleted worker #{worker_description}")
|
27
|
+
unlocked_jobs(worker).each do |unlocked_job|
|
28
|
+
io.puts("Unlocked orphaned job #{unlocked_job.id} from worker #{worker_description}")
|
29
|
+
end
|
19
30
|
end
|
20
|
-
|
21
|
-
unlocked_jobs.each do |unlocked_job|
|
22
|
-
worker = worker_map[unlocked_job.locked_by]
|
23
|
-
worker_string = worker ? worker_description(worker) : unlocked_job.locked_by
|
24
|
-
io.puts("Unlocked orphaned job #{unlocked_job.id} from worker #{worker_string}")
|
25
|
-
end
|
26
|
-
|
27
|
-
io.string
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def worker_map
|
33
|
-
@worker_map ||= workers.each_with_object(Hash.new) do |worker, worker_map|
|
34
|
-
worker_map[worker.name] = worker
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def worker_description(worker)
|
39
|
-
"#{worker.label}(#{worker.name})"
|
31
|
+
io.string.rstrip
|
40
32
|
end
|
41
33
|
end
|
42
34
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'set'
|
2
4
|
|
3
5
|
module Delayed
|
@@ -6,12 +8,10 @@ module Delayed
|
|
6
8
|
|
7
9
|
callbacks do |lifecycle|
|
8
10
|
lifecycle.before(:execute) do |worker|
|
9
|
-
if Delayed::Heartbeat.configuration.enabled?
|
10
|
-
@heartbeat = Delayed::Heartbeat::WorkerHeartbeat.new(worker.name)
|
11
|
-
end
|
11
|
+
@heartbeat = Delayed::Heartbeat::WorkerHeartbeat.new(worker.name) if Delayed::Heartbeat.configuration.enabled?
|
12
12
|
end
|
13
13
|
|
14
|
-
lifecycle.after(:execute) do |
|
14
|
+
lifecycle.after(:execute) do |_worker|
|
15
15
|
@heartbeat.stop if @heartbeat
|
16
16
|
end
|
17
17
|
end
|
@@ -19,4 +19,3 @@ module Delayed
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
22
|
-
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
namespace :delayed do
|
2
4
|
namespace :heartbeat do
|
3
5
|
desc 'Cleans up workers that have not heartbeated recently.'
|
@@ -18,7 +20,7 @@ namespace :delayed do
|
|
18
20
|
end
|
19
21
|
|
20
22
|
def verbose?
|
21
|
-
ENV['VERBOSE'].to_s.
|
23
|
+
ENV['VERBOSE'].to_s.casecmp('true').zero?
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'delayed/heartbeat/compatibility'
|
2
4
|
|
3
5
|
module Delayed
|
@@ -43,7 +45,7 @@ module Delayed
|
|
43
45
|
end
|
44
46
|
|
45
47
|
def self.workers_with_different_version(current_version)
|
46
|
-
where('version != ?',
|
48
|
+
where('version != ?', current_version)
|
47
49
|
end
|
48
50
|
|
49
51
|
def self.delete_workers(workers)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Delayed
|
2
4
|
module Heartbeat
|
3
5
|
class WorkerHeartbeat
|
@@ -40,12 +42,13 @@ module Delayed
|
|
40
42
|
def run_heartbeat_loop
|
41
43
|
loop do
|
42
44
|
break if sleep_interruptibly(heartbeat_interval)
|
45
|
+
|
43
46
|
update_heartbeat
|
44
47
|
# Return the connection back to the pool since we won't be needing
|
45
48
|
# it again for a while.
|
46
49
|
Delayed::Backend::ActiveRecord::Job.clear_active_connections!
|
47
50
|
end
|
48
|
-
rescue => e
|
51
|
+
rescue StandardError => e
|
49
52
|
# We don't want the worker to continue running if the heartbeat can't be written.
|
50
53
|
# Don't use Thread.abort_on_exception because that will give Delayed::Job a chance
|
51
54
|
# to mark the job as failed which will unlock it even though the clock
|
@@ -65,8 +68,8 @@ module Delayed
|
|
65
68
|
if heartbeat_delta_seconds < heartbeat_timeout_seconds || self_termination_disabled?
|
66
69
|
@worker_model.update_column(:last_heartbeat_at, now)
|
67
70
|
else
|
68
|
-
raise Timeout::Error
|
69
|
-
"exceeds timeout\n. Current job: #{
|
71
|
+
raise Timeout::Error.new("Worker heartbeat not updated for #{heartbeat_delta_seconds} seconds which " \
|
72
|
+
"exceeds timeout\n. Current job: #{@worker_model.job.inspect}")
|
70
73
|
end
|
71
74
|
end
|
72
75
|
|
data/lib/delayed/heartbeat.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'delayed/heartbeat/compatibility'
|
2
4
|
require 'delayed/heartbeat/configuration'
|
3
5
|
require 'delayed/heartbeat/delete_worker_results'
|
@@ -16,9 +18,7 @@ module Delayed
|
|
16
18
|
yield(configuration) if block_given?
|
17
19
|
end
|
18
20
|
|
19
|
-
|
20
|
-
@configuration
|
21
|
-
end
|
21
|
+
attr_reader :configuration
|
22
22
|
|
23
23
|
def delete_workers_with_different_version(current_version = configuration.worker_version)
|
24
24
|
old_workers = Delayed::Heartbeat::Worker.workers_with_different_version(current_version)
|
@@ -34,11 +34,11 @@ module Delayed
|
|
34
34
|
|
35
35
|
def cleanup_workers(workers, mark_attempt_failed: true)
|
36
36
|
Delayed::Heartbeat::Worker.transaction do
|
37
|
-
|
38
|
-
worker.unlock_jobs(mark_attempt_failed: mark_attempt_failed)
|
37
|
+
worker_job_map = workers.each_with_object(Hash.new) do |worker, result|
|
38
|
+
result[worker] = worker.unlock_jobs(mark_attempt_failed: mark_attempt_failed)
|
39
39
|
end
|
40
40
|
Delayed::Heartbeat::Worker.delete_workers(workers)
|
41
|
-
Delayed::Heartbeat::DeleteWorkerResults.new(
|
41
|
+
Delayed::Heartbeat::DeleteWorkerResults.new(worker_job_map)
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rails/generators'
|
2
4
|
require 'rails/generators/migration'
|
3
5
|
require 'rails/generators/active_record'
|
@@ -6,10 +8,10 @@ module DelayedJobHeartbeatPlugin
|
|
6
8
|
class InstallGenerator < Rails::Generators::Base
|
7
9
|
include Rails::Generators::Migration
|
8
10
|
|
9
|
-
|
11
|
+
source_paths << File.join(File.dirname(__FILE__), 'templates')
|
10
12
|
|
11
13
|
def create_migration_file
|
12
|
-
migration_template('migration.
|
14
|
+
migration_template('migration.erb', 'db/migrate/create_delayed_workers.rb')
|
13
15
|
end
|
14
16
|
|
15
17
|
def self.next_migration_number(dirname)
|
data/spec/db/schema.rb
CHANGED
@@ -1,34 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Delayed::Heartbeat::DeleteWorkerResults do
|
4
6
|
let(:worker) { create_worker(name: 'my-worker') }
|
5
7
|
let(:job) { create_job(locked_by: worker.name) }
|
6
|
-
let(:results) { create_results(
|
8
|
+
let(:results) { create_results(worker => [job]) }
|
7
9
|
|
8
10
|
describe "#workers" do
|
9
11
|
specify { expect(results.workers).to eq [worker] }
|
10
12
|
end
|
11
13
|
|
12
14
|
describe "#unlocked_jobs" do
|
13
|
-
|
15
|
+
let(:other_worker) { create_worker(name: 'my-other-worker') }
|
16
|
+
let(:other_job) { create_job(locked_by: worker.name) }
|
17
|
+
let(:results) { create_results(worker => [job], other_worker => [other_job]) }
|
18
|
+
|
19
|
+
specify { expect(results.unlocked_jobs(worker)).to eq [job] }
|
20
|
+
specify { expect(results.unlocked_jobs).to match_array [job, other_job] }
|
14
21
|
end
|
15
22
|
|
16
23
|
describe "#to_s" do
|
17
24
|
it "includes workers" do
|
18
|
-
results = create_results(
|
25
|
+
results = create_results(worker => [])
|
19
26
|
expect(results.to_s).to include(worker.name)
|
20
27
|
end
|
21
28
|
|
22
|
-
it "includes jobs for
|
23
|
-
results = create_results([worker], [job])
|
24
|
-
expect(results.to_s).to include(job.id.to_s)
|
25
|
-
end
|
26
|
-
|
27
|
-
it "includes jobs locked by an unknown worker" do
|
28
|
-
job = create_job(locked_by: 'unknown-worker')
|
29
|
-
results = create_results([], [job])
|
29
|
+
it "includes jobs for workers" do
|
30
30
|
expect(results.to_s).to include(job.id.to_s)
|
31
|
-
expect(results.to_s).to include(job.locked_by)
|
32
31
|
end
|
33
32
|
end
|
34
33
|
|
@@ -41,7 +40,7 @@ describe Delayed::Heartbeat::DeleteWorkerResults do
|
|
41
40
|
Delayed::Job.create!(attributes)
|
42
41
|
end
|
43
42
|
|
44
|
-
def create_results(
|
45
|
-
Delayed::Heartbeat::DeleteWorkerResults.new(
|
43
|
+
def create_results(worker_job_map)
|
44
|
+
Delayed::Heartbeat::DeleteWorkerResults.new(worker_job_map)
|
46
45
|
end
|
47
46
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
|
2
4
|
|
3
5
|
require 'simplecov'
|
4
6
|
require 'coveralls'
|
5
7
|
|
6
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter
|
7
|
-
|
8
|
-
|
9
|
-
]
|
8
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
|
9
|
+
[SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter]
|
10
|
+
)
|
10
11
|
SimpleCov.start do
|
11
12
|
add_filter 'spec'
|
12
13
|
end
|
@@ -30,27 +31,38 @@ Delayed::Worker.logger.level = Logger::DEBUG
|
|
30
31
|
ActiveRecord::Base.logger = Delayed::Worker.logger
|
31
32
|
ActiveRecord::Migration.verbose = false
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
require 'db/schema'
|
34
|
+
database_name = 'delayed_job_heartbeat_plugin_test'
|
35
|
+
database_host = ENV.fetch('PGHOST', 'localhost')
|
36
|
+
database_port = ENV.fetch('PGPORT', 5432)
|
37
37
|
|
38
38
|
RSpec.configure do |config|
|
39
39
|
config.order = 'random'
|
40
40
|
|
41
41
|
config.before(:suite) do
|
42
|
+
db_connection_args = "--host #{database_host} --port #{database_port}"
|
43
|
+
`dropdb #{db_connection_args} --if-exists #{database_name} 2> /dev/null`
|
44
|
+
`createdb #{db_connection_args} #{database_name}`
|
45
|
+
|
46
|
+
pg_version = `psql #{db_connection_args} --dbname #{database_name} --tuples-only --command "select version()";`
|
47
|
+
puts "Testing with Postgres version: #{pg_version.strip}"
|
48
|
+
puts "Testing with ActiveRecord #{ActiveRecord::VERSION::STRING}"
|
49
|
+
|
50
|
+
database_url = "postgres://#{database_host}:#{database_port}/#{database_name}"
|
51
|
+
puts "Using database #{database_url}"
|
52
|
+
ActiveRecord::Base.establish_connection(database_url)
|
53
|
+
require 'db/schema'
|
42
54
|
DatabaseCleaner.clean_with(:truncation)
|
43
55
|
end
|
44
56
|
|
45
|
-
config.before
|
57
|
+
config.before do |example|
|
46
58
|
DatabaseCleaner.strategy = example.metadata.fetch(:cleaner_strategy, :transaction)
|
47
59
|
end
|
48
60
|
|
49
|
-
config.before
|
61
|
+
config.before do
|
50
62
|
DatabaseCleaner.start
|
51
63
|
end
|
52
64
|
|
53
|
-
config.after
|
65
|
+
config.after do
|
54
66
|
DatabaseCleaner.clean
|
55
67
|
end
|
56
68
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RSpec::Matchers.define :have_been_destroyed do
|
4
4
|
match do |actual|
|
@@ -6,7 +6,7 @@ RSpec::Matchers.define :have_been_destroyed do
|
|
6
6
|
end
|
7
7
|
|
8
8
|
description do
|
9
|
-
|
9
|
+
'model should have been destroyed'
|
10
10
|
end
|
11
11
|
|
12
12
|
failure_message do |actual|
|
data/spec/support/test_job.rb
CHANGED
data/spec/support/wait.rb
CHANGED
metadata
CHANGED
@@ -1,159 +1,215 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delayed_job_heartbeat_plugin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel Turkel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-04-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: delayed_job
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 4.1.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 4.1.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: delayed_job_active_record
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 4.1.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 4.1.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: activerecord
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
48
|
-
- - <
|
47
|
+
version: '5.2'
|
48
|
+
- - "<"
|
49
49
|
- !ruby/object:Gem::Version
|
50
|
-
version: '
|
50
|
+
version: '7.1'
|
51
51
|
type: :development
|
52
52
|
prerelease: false
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
54
54
|
requirements:
|
55
|
-
- -
|
55
|
+
- - ">="
|
56
56
|
- !ruby/object:Gem::Version
|
57
|
-
version: '
|
58
|
-
- - <
|
57
|
+
version: '5.2'
|
58
|
+
- - "<"
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: '
|
60
|
+
version: '7.1'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
|
-
name:
|
62
|
+
name: appraisal
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
|
-
- -
|
65
|
+
- - ">="
|
66
66
|
- !ruby/object:Gem::Version
|
67
67
|
version: '0'
|
68
68
|
type: :development
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
|
-
- -
|
72
|
+
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: bundler
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: coveralls_reborn
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 0.18.0
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 0.18.0
|
75
103
|
- !ruby/object:Gem::Dependency
|
76
104
|
name: database_cleaner
|
77
105
|
requirement: !ruby/object:Gem::Requirement
|
78
106
|
requirements:
|
79
|
-
- -
|
107
|
+
- - ">="
|
80
108
|
- !ruby/object:Gem::Version
|
81
109
|
version: '1.2'
|
82
110
|
type: :development
|
83
111
|
prerelease: false
|
84
112
|
version_requirements: !ruby/object:Gem::Requirement
|
85
113
|
requirements:
|
86
|
-
- -
|
114
|
+
- - ">="
|
87
115
|
- !ruby/object:Gem::Version
|
88
116
|
version: '1.2'
|
89
117
|
- !ruby/object:Gem::Dependency
|
90
|
-
name:
|
118
|
+
name: pg
|
91
119
|
requirement: !ruby/object:Gem::Requirement
|
92
120
|
requirements:
|
93
|
-
- -
|
121
|
+
- - ">="
|
94
122
|
- !ruby/object:Gem::Version
|
95
123
|
version: '0'
|
96
124
|
type: :development
|
97
125
|
prerelease: false
|
98
126
|
version_requirements: !ruby/object:Gem::Requirement
|
99
127
|
requirements:
|
100
|
-
- -
|
128
|
+
- - ">="
|
101
129
|
- !ruby/object:Gem::Version
|
102
130
|
version: '0'
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: rake
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - "~>"
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '13.0'
|
138
|
+
type: :development
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - "~>"
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '13.0'
|
103
145
|
- !ruby/object:Gem::Dependency
|
104
146
|
name: rspec
|
105
147
|
requirement: !ruby/object:Gem::Requirement
|
106
148
|
requirements:
|
107
|
-
- -
|
149
|
+
- - "~>"
|
108
150
|
- !ruby/object:Gem::Version
|
109
|
-
version: 3
|
151
|
+
version: '3'
|
110
152
|
type: :development
|
111
153
|
prerelease: false
|
112
154
|
version_requirements: !ruby/object:Gem::Requirement
|
113
155
|
requirements:
|
114
|
-
- -
|
156
|
+
- - "~>"
|
115
157
|
- !ruby/object:Gem::Version
|
116
|
-
version: 3
|
158
|
+
version: '3'
|
117
159
|
- !ruby/object:Gem::Dependency
|
118
|
-
name:
|
160
|
+
name: rspec_junit_formatter
|
119
161
|
requirement: !ruby/object:Gem::Requirement
|
120
162
|
requirements:
|
121
|
-
- -
|
163
|
+
- - ">="
|
122
164
|
- !ruby/object:Gem::Version
|
123
|
-
version: 0
|
165
|
+
version: '0'
|
124
166
|
type: :development
|
125
167
|
prerelease: false
|
126
168
|
version_requirements: !ruby/object:Gem::Requirement
|
127
169
|
requirements:
|
128
|
-
- -
|
170
|
+
- - ">="
|
129
171
|
- !ruby/object:Gem::Version
|
130
|
-
version: 0
|
172
|
+
version: '0'
|
131
173
|
- !ruby/object:Gem::Dependency
|
132
|
-
name:
|
174
|
+
name: salsify_rubocop
|
133
175
|
requirement: !ruby/object:Gem::Requirement
|
134
176
|
requirements:
|
135
|
-
- -
|
177
|
+
- - "~>"
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: 1.0.2
|
180
|
+
type: :development
|
181
|
+
prerelease: false
|
182
|
+
version_requirements: !ruby/object:Gem::Requirement
|
183
|
+
requirements:
|
184
|
+
- - "~>"
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: 1.0.2
|
187
|
+
- !ruby/object:Gem::Dependency
|
188
|
+
name: simplecov
|
189
|
+
requirement: !ruby/object:Gem::Requirement
|
190
|
+
requirements:
|
191
|
+
- - ">="
|
136
192
|
- !ruby/object:Gem::Version
|
137
193
|
version: '0'
|
138
194
|
type: :development
|
139
195
|
prerelease: false
|
140
196
|
version_requirements: !ruby/object:Gem::Requirement
|
141
197
|
requirements:
|
142
|
-
- -
|
198
|
+
- - ">="
|
143
199
|
- !ruby/object:Gem::Version
|
144
200
|
version: '0'
|
145
201
|
- !ruby/object:Gem::Dependency
|
146
|
-
name:
|
202
|
+
name: timecop
|
147
203
|
requirement: !ruby/object:Gem::Requirement
|
148
204
|
requirements:
|
149
|
-
- -
|
205
|
+
- - ">="
|
150
206
|
- !ruby/object:Gem::Version
|
151
207
|
version: '0'
|
152
208
|
type: :development
|
153
209
|
prerelease: false
|
154
210
|
version_requirements: !ruby/object:Gem::Requirement
|
155
211
|
requirements:
|
156
|
-
- -
|
212
|
+
- - ">="
|
157
213
|
- !ruby/object:Gem::Version
|
158
214
|
version: '0'
|
159
215
|
description:
|
@@ -163,15 +219,22 @@ executables: []
|
|
163
219
|
extensions: []
|
164
220
|
extra_rdoc_files: []
|
165
221
|
files:
|
166
|
-
- .
|
167
|
-
- .
|
168
|
-
- .
|
222
|
+
- ".circleci/config.yml"
|
223
|
+
- ".github/CODEOWNERS"
|
224
|
+
- ".gitignore"
|
225
|
+
- ".rspec"
|
226
|
+
- ".rubocop.yml"
|
227
|
+
- Appraisals
|
228
|
+
- CHANGELOG.md
|
169
229
|
- Gemfile
|
170
230
|
- LICENSE.txt
|
171
231
|
- README.md
|
172
232
|
- Rakefile
|
173
233
|
- bin/setup
|
174
234
|
- delayed_job_heartbeat_plugin.gemspec
|
235
|
+
- gemfiles/rails_6.0.gemfile
|
236
|
+
- gemfiles/rails_6.1.gemfile
|
237
|
+
- gemfiles/rails_7.0.gemfile
|
175
238
|
- lib/delayed/heartbeat.rb
|
176
239
|
- lib/delayed/heartbeat/compatibility.rb
|
177
240
|
- lib/delayed/heartbeat/configuration.rb
|
@@ -184,8 +247,7 @@ files:
|
|
184
247
|
- lib/delayed/heartbeat/worker_heartbeat.rb
|
185
248
|
- lib/delayed_job_heartbeat_plugin.rb
|
186
249
|
- lib/generators/delayed_job_heartbeat_plugin/install_generator.rb
|
187
|
-
- lib/generators/delayed_job_heartbeat_plugin/templates/migration.
|
188
|
-
- spec/db/database.yml
|
250
|
+
- lib/generators/delayed_job_heartbeat_plugin/templates/migration.erb
|
189
251
|
- spec/db/schema.rb
|
190
252
|
- spec/delayed/heartbeat/delete_worker_results_spec.rb
|
191
253
|
- spec/delayed/heartbeat/worker_heartbeat_spec.rb
|
@@ -198,29 +260,29 @@ files:
|
|
198
260
|
homepage: https://github.com/salsify/delayed_job_heartbeat_plugin
|
199
261
|
licenses:
|
200
262
|
- MIT
|
201
|
-
metadata:
|
263
|
+
metadata:
|
264
|
+
allowed_push_host: https://rubygems.org
|
265
|
+
rubygems_mfa_required: 'true'
|
202
266
|
post_install_message:
|
203
267
|
rdoc_options: []
|
204
268
|
require_paths:
|
205
269
|
- lib
|
206
270
|
required_ruby_version: !ruby/object:Gem::Requirement
|
207
271
|
requirements:
|
208
|
-
- -
|
272
|
+
- - ">="
|
209
273
|
- !ruby/object:Gem::Version
|
210
|
-
version: '2.
|
274
|
+
version: '2.7'
|
211
275
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
212
276
|
requirements:
|
213
|
-
- -
|
277
|
+
- - ">="
|
214
278
|
- !ruby/object:Gem::Version
|
215
279
|
version: '0'
|
216
280
|
requirements: []
|
217
|
-
|
218
|
-
rubygems_version: 2.2.2
|
281
|
+
rubygems_version: 3.2.33
|
219
282
|
signing_key:
|
220
283
|
specification_version: 4
|
221
284
|
summary: Delayed::Job plugin to unlock jobs from dead workers
|
222
285
|
test_files:
|
223
|
-
- spec/db/database.yml
|
224
286
|
- spec/db/schema.rb
|
225
287
|
- spec/delayed/heartbeat/delete_worker_results_spec.rb
|
226
288
|
- spec/delayed/heartbeat/worker_heartbeat_spec.rb
|
data/.travis.yml
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
sudo: false
|
2
|
-
language: ruby
|
3
|
-
before_install: gem install bundler -v 1.10.6
|
4
|
-
env:
|
5
|
-
matrix:
|
6
|
-
- RAILS_VERSION="~> 3.2.22"
|
7
|
-
- RAILS_VERSION="~> 4.0.13"
|
8
|
-
- RAILS_VERSION="~> 4.1.13"
|
9
|
-
- RAILS_VERSION="~> 4.2.4"
|
10
|
-
rvm:
|
11
|
-
- 2.0.0
|
12
|
-
- 2.1.7
|
13
|
-
- 2.2.3
|
14
|
-
|