inst-jobs 2.1.3 → 2.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4c31ed6d846425c9bf022bb8c744681019cbf0f0192d4e0ee7f0a5d7dc44a65c
4
- data.tar.gz: 4a5b940ba8bd6770209d93e20ccc217d4ab5915bcd1a5791de70b076e7cecf97
3
+ metadata.gz: 35a651c7d168b0e569ebc47f13ed3500bd10d813308993ecdbfbc176e74943a5
4
+ data.tar.gz: eba8a2e50f5414684045bde99d5ccc1dc144d00f6b84d3bb82ec5c6becc34003
5
5
  SHA512:
6
- metadata.gz: 07377763c26979774add4b3445aa72ebc2cbff6aabe595e1157c883a90dea48407bc8ecb87f5532265178a96b27548caaf5ce13a0789c469272980bc864a2882
7
- data.tar.gz: 7ddd291e18be337ae1d858d016af92cc255c111e5141eafca8cee598fcdae9563a74983ba6b98daeb50c1fe599490dd9c962e1c722d5dcea5083bf16a619641d
6
+ metadata.gz: bc667a0ce1380f8acfe092bdf938d06e8d2dfff1018f53679930f88c8ffa45bf088e758fd362f99c5835600527f5a3d2cf189e7560dd6ecce57850d64682f178
7
+ data.tar.gz: 83d984683717018254316d891a972809bf7c3597628d94de149a4af0dab2efe5cf77473a6580408ec461c0d8dddc206b03e8747cbe6f22ba2f169194be876210
@@ -13,9 +13,13 @@ end
13
13
  module Delayed
14
14
  module Backend
15
15
  module ActiveRecord
16
+ class AbstractJob < ::ActiveRecord::Base
17
+ self.abstract_class = true
18
+ end
19
+
16
20
  # A job object that is persisted to the database.
17
21
  # Contains the work object as a YAML field.
18
- class Job < ::ActiveRecord::Base
22
+ class Job < AbstractJob
19
23
  include Delayed::Backend::Base
20
24
  self.table_name = :delayed_jobs
21
25
 
@@ -27,7 +31,7 @@ module Delayed
27
31
 
28
32
  class << self
29
33
  def create(attributes, &block)
30
- return super if connection.prepared_statements || Rails.version < '5.2'
34
+ return super if connection.prepared_statements
31
35
 
32
36
  # modified from ActiveRecord::Persistence.create and ActiveRecord::Persistence#_insert_record
33
37
  job = new(attributes, &block)
@@ -37,7 +41,7 @@ module Delayed
37
41
 
38
42
  def single_step_create
39
43
  connection = self.class.connection
40
- return save if connection.prepared_statements || Rails.version < '5.2'
44
+ return save if connection.prepared_statements
41
45
 
42
46
  # a before_save callback that we're skipping
43
47
  initialize_defaults
@@ -66,7 +70,8 @@ module Delayed
66
70
  # > Multiple queries sent in a single PQexec call are processed in a single transaction,
67
71
  # unless there are explicit BEGIN/COMMIT commands included in the query string to divide
68
72
  # it into multiple transactions.
69
- sql = "SELECT pg_advisory_xact_lock(#{connection.quote_table_name('half_md5_as_bigint')}(#{connection.quote(values['strand'])})); #{sql}" if values["strand"]
73
+ # but we don't need to lock when inserting into Delayed::Failed
74
+ sql = "SELECT pg_advisory_xact_lock(#{connection.quote_table_name('half_md5_as_bigint')}(#{connection.quote(values['strand'])})); #{sql}" if values["strand"] && self.class == Job
70
75
  result = connection.execute(sql, "#{self} Create")
71
76
  self.id = result.values.first.first
72
77
  result.clear
@@ -98,7 +103,7 @@ module Delayed
98
103
  # to raise the lock level
99
104
  before_create :lock_strand_on_create
100
105
  def lock_strand_on_create
101
- if strand.present?
106
+ if strand.present? && self.class == Job
102
107
  self.class.connection.execute("SELECT pg_advisory_xact_lock(#{self.class.connection.quote_table_name('half_md5_as_bigint')}(#{self.class.connection.quote(strand)}))")
103
108
  end
104
109
  end
@@ -513,17 +518,6 @@ module Delayed
513
518
  class Failed < Job
514
519
  include Delayed::Backend::Base
515
520
  self.table_name = :failed_jobs
516
- # Rails hasn't completely loaded yet, and setting the table name will cache some stuff
517
- # so reset that cache so that it will load correctly after Rails is all loaded
518
- # It's fixed in Rails 5 to not cache anything when you set the table_name
519
- if Rails.version < '5' && Rails.version >= '4.2'
520
- @arel_engine = nil
521
- @arel_table = nil
522
- end
523
- end
524
- if Rails.version < '5' && Rails.version >= '4.2'
525
- @arel_engine = nil
526
- @arel_table = nil
527
521
  end
528
522
  end
529
523
 
@@ -56,6 +56,12 @@ module Delayed
56
56
  kwargs[:expires_at] = expires_at
57
57
  kwargs[:queue] = queue
58
58
 
59
+ strand_args = 0
60
+ strand_args += 1 if strand
61
+ strand_args += 1 if n_strand
62
+ strand_args += 1 if singleton
63
+ raise ArgumentError, "Only one of strand, n_strand, or singleton can be used" if strand_args > 1
64
+
59
65
  # If two parameters are given to n_strand, the first param is used
60
66
  # as the strand name for looking up the Setting, while the second
61
67
  # param is appended to make a unique set of strands.
@@ -395,13 +395,6 @@ class Job
395
395
  result
396
396
  end
397
397
 
398
- if Rails.version < "4.1"
399
- def changes_applied
400
- @previously_changed = changes
401
- @changed_attributes.clear
402
- end
403
- end
404
-
405
398
  def save!(*a)
406
399
  save(*a) || raise(RecordNotSaved)
407
400
  end
@@ -53,18 +53,12 @@ class Periodic
53
53
  end
54
54
 
55
55
  def enqueue_args
56
- # yes, checking for whether it is actually the boolean literal false,
57
- # which means the consuming code really does not want this job to be
58
- # a singleton at all.
59
- non_singleton_periodic_job = @job_args[:singleton] == false
60
56
  inferred_args = {
61
57
  max_attempts: 1,
62
58
  run_at: @cron.next_time(Delayed::Periodic.now).utc.to_time,
63
- singleton: (non_singleton_periodic_job ? nil : tag)
59
+ singleton: tag,
60
+ on_conflict: :patient
64
61
  }
65
- unless non_singleton_periodic_job
66
- inferred_args[:on_conflict] = :patient
67
- end
68
62
  @job_args.merge(inferred_args)
69
63
  end
70
64
 
data/lib/delayed/pool.rb CHANGED
@@ -39,6 +39,7 @@ class Pool
39
39
  Process.wait unlock_pid
40
40
 
41
41
  spawn_periodic_auditor
42
+ spawn_abandoned_job_cleanup
42
43
  spawn_all_workers
43
44
  say "Workers spawned"
44
45
  join
@@ -105,12 +106,41 @@ class Pool
105
106
  # db connections with the parent
106
107
  def fork_with_reconnects
107
108
  fork do
109
+ @self_pipe.each(&:close) # sub-processes don't need to wake us up; keep their FDs clean
108
110
  Pool.on_fork.()
109
111
  Delayed::Job.reconnect!
110
112
  yield
111
113
  end
112
114
  end
113
115
 
116
+ def spawn_abandoned_job_cleanup
117
+ return if Settings.disable_abandoned_job_cleanup
118
+ cleanup_interval_in_minutes = 60
119
+ @abandoned_cleanup_thread = Thread.new do
120
+ # every hour (staggered by process)
121
+ # check for dead jobs and cull them.
122
+ # Will actually be more often based on the
123
+ # number of worker nodes in the pool. This will actually
124
+ # be a max of N times per hour where N is the number of workers,
125
+ # but they won't overrun each other because the health check
126
+ # takes an advisory lock internally
127
+ sleep(rand(cleanup_interval_in_minutes * 60))
128
+ loop do
129
+ schedule_abandoned_job_cleanup
130
+ sleep(cleanup_interval_in_minutes * 60)
131
+ end
132
+ end
133
+ end
134
+
135
+ def schedule_abandoned_job_cleanup
136
+ pid = fork_with_reconnects do
137
+ # we want to avoid db connections in the main pool process
138
+ $0 = "delayed_abandoned_job_cleanup"
139
+ Delayed::Worker::HealthCheck.reschedule_abandoned_jobs
140
+ end
141
+ workers[pid] = :abandoned_job_cleanup
142
+ end
143
+
114
144
  def spawn_periodic_auditor
115
145
  return if Settings.disable_periodic_jobs
116
146
 
@@ -217,6 +247,8 @@ class Pool
217
247
  case worker
218
248
  when :periodic_audit
219
249
  say "ran auditor: #{worker}"
250
+ when :abandoned_job_cleanup
251
+ say "ran cleanup: #{worker}"
220
252
  when :work_queue
221
253
  say "work queue exited, restarting", :info
222
254
  spawn_work_queue
@@ -8,6 +8,7 @@ module Delayed
8
8
  module Settings
9
9
  SETTINGS = [
10
10
  :default_job_options,
11
+ :disable_abandoned_job_cleanup,
11
12
  :disable_periodic_jobs,
12
13
  :disable_automatic_orphan_unlocking,
13
14
  :fetch_batch_size,
@@ -83,7 +84,7 @@ module Delayed
83
84
  def self.worker_config(config_filename = nil)
84
85
  config_filename ||= default_worker_config_name
85
86
  config = YAML.load(ERB.new(File.read(config_filename)).result)
86
- env = defined?(RAILS_ENV) ? RAILS_ENV : ENV['RAILS_ENV'] || 'development'
87
+ env = Rails.env || 'development'
87
88
  config = config[env] || config['default']
88
89
  # Backwards compatibility from when the config was just an array of queues
89
90
  config = { :workers => config } if config.is_a?(Array)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Delayed
4
- VERSION = "2.1.3"
4
+ VERSION = "2.3.2"
5
5
  end
@@ -16,6 +16,7 @@ class InProcess
16
16
  end
17
17
 
18
18
  # intentional nops for compatibility w/ parent process
19
+ def init; end
19
20
  def close; end
20
21
  def wake_up; end
21
22
  end
@@ -11,7 +11,10 @@ class ParentProcess
11
11
  def initialize(addrinfo, config: Settings.parent_process)
12
12
  @addrinfo = addrinfo
13
13
  @connect_timeout = config['client_connect_timeout'] || 2
14
- @self_pipe = IO.pipe
14
+ end
15
+
16
+ def init
17
+ @self_pipe ||= IO.pipe
15
18
  end
16
19
 
17
20
  def close
@@ -69,7 +69,6 @@ class Worker
69
69
  @config = options
70
70
  @job_count = 0
71
71
 
72
- @self_pipe = IO.pipe
73
72
  @signal_queue = []
74
73
 
75
74
  app = Rails.application
@@ -120,6 +119,8 @@ class Worker
120
119
  def start
121
120
  logger.info "Starting worker"
122
121
  set_process_name("start:#{Settings.worker_procname_prefix}#{@queue_name}:#{min_priority || 0}:#{max_priority || 'max'}")
122
+ @self_pipe = IO.pipe
123
+ work_queue.init
123
124
 
124
125
  work_thread = Thread.current
125
126
  SIGNALS.each do |sig|
@@ -162,6 +163,9 @@ class Worker
162
163
  signal_processor.kill
163
164
  signal_processor.join
164
165
  end
166
+
167
+ @self_pipe&.each(&:close)
168
+ @self_pipe = nil
165
169
  end
166
170
 
167
171
  def cleanup!
@@ -9,52 +9,49 @@ module Delayed
9
9
  class ConsulHealthCheck < HealthCheck
10
10
  self.type_name = :consul
11
11
 
12
- CONSUL_CONFIG_KEYS = %w{url host port ssl token connect_timeout receive_timeout send_timeout}.map(&:freeze).freeze
12
+ CONSUL_CONFIG_KEYS = %w{url acl_token}.map(&:freeze).freeze
13
13
  DEFAULT_SERVICE_NAME = 'inst-jobs_worker'.freeze
14
- attr_reader :agent_client, :catalog_client
14
+ attr_reader :service_client, :health_client
15
15
 
16
16
  def initialize(*, **)
17
17
  super
18
18
  # Because we don't want the consul client to be a hard dependency we're
19
19
  # only requiring it once it's absolutely needed
20
- require 'imperium'
20
+ require 'diplomat'
21
21
 
22
22
  if config.keys.any? { |k| CONSUL_CONFIG_KEYS.include?(k) }
23
- consul_config = Imperium::Configuration.new.tap do |conf|
23
+ consul_config = Diplomat::Configuration.new.tap do |conf|
24
24
  CONSUL_CONFIG_KEYS.each do |key|
25
25
  conf.send("#{key}=", config[key]) if config[key]
26
26
  end
27
27
  end
28
- @agent_client = Imperium::Agent.new(consul_config)
29
- @catalog_client = Imperium::Catalog.new(consul_config)
28
+ @service_client = Diplomat::Service.new(configuration: consul_config)
29
+ @health_client = Diplomat::Health.new(configuration: consul_config)
30
30
  else
31
- @agent_client = Imperium::Agent.default_client
32
- @catalog_client = Imperium::Catalog.default_client
31
+ @service_client = Diplomat::Service.new
32
+ @health_client = Diplomat::Health.new
33
33
  end
34
34
  end
35
35
 
36
36
  def start
37
- service = Imperium::Service.new({
37
+ @service_client.register({
38
38
  id: worker_name,
39
39
  name: service_name,
40
+ check: check_attributes
40
41
  })
41
- service.add_check(check_attributes)
42
- response = @agent_client.register_service(service)
43
- response.ok?
44
42
  end
45
43
 
46
44
  def stop
47
- response = @agent_client.deregister_service(worker_name)
48
- response.ok? || response.not_found?
45
+ @service_client.deregister(worker_name)
49
46
  end
50
47
 
51
48
  def live_workers
52
- live_nodes = @catalog_client.list_nodes_for_service(service_name)
53
- if live_nodes.ok?
54
- live_nodes.map(&:service_id)
55
- else
56
- raise "Unable to read from Consul catalog: #{live_nodes.content}"
57
- end
49
+ # Filter out critical workers (probably nodes failing their serf health check)
50
+ live_nodes = @health_client.service(service_name, {
51
+ filter: 'not Checks.Status == critical'
52
+ })
53
+
54
+ live_nodes.map { |n| n.Service['ID']}
58
55
  end
59
56
 
60
57
  private
@@ -23,12 +23,13 @@ module Delayed
23
23
  def reschedule_abandoned_jobs
24
24
  return if Settings.worker_health_check_type == :none
25
25
  Delayed::Job.transaction do
26
- # this job is a special case, and is not a singleton
26
+ # this action is a special case, and SHOULD NOT be a periodic job
27
27
  # because if it gets wiped out suddenly during execution
28
28
  # it can't go clean up it's abandoned self. Therefore,
29
- # we try to get an advisory lock when it runs. If we succeed,
30
- # no other job is trying to do this right now (and if we abandon the
31
- # job, the transaction will end, releasing the advisory lock).
29
+ # we expect it to get run from it's own process forked from the job pool
30
+ # and we try to get an advisory lock when it runs. If we succeed,
31
+ # no other worker is trying to do this right now (and if we abandon the
32
+ # operation, the transaction will end, releasing the advisory lock).
32
33
  result = attempt_advisory_lock
33
34
  return unless result
34
35
  checker = Worker::HealthCheck.build(
data/lib/delayed_job.rb CHANGED
@@ -18,6 +18,7 @@ require 'rails'
18
18
  require 'active_support/core_ext/module/attribute_accessors'
19
19
  require 'active_record'
20
20
  require 'after_transaction_commit'
21
+ require 'debug_inspector'
21
22
 
22
23
  require 'delayed/core_ext/kernel'
23
24
 
@@ -262,8 +262,6 @@ describe 'Delayed::Backed::ActiveRecord::Job' do
262
262
 
263
263
  context "non-transactional", non_transactional: true do
264
264
  it "creates a stranded job in a single statement" do
265
- skip "Requires Rails 5.2 or greater" unless Rails.version >= '5.2'
266
-
267
265
  allow(Delayed::Job.connection).to receive(:prepared_statements).and_return(false)
268
266
  allow(Delayed::Job.connection).to receive(:execute).with(be_include("pg_advisory_xact_lock"), anything).and_call_original.once
269
267
  allow(Delayed::Job.connection).to receive(:insert).never
@@ -273,8 +271,6 @@ describe 'Delayed::Backed::ActiveRecord::Job' do
273
271
  end
274
272
 
275
273
  it "creates a non-stranded job in a single statement" do
276
- skip "Requires Rails 5.2 or greater" unless Rails.version >= '5.2'
277
-
278
274
  allow(Delayed::Job.connection).to receive(:prepared_statements).and_return(false)
279
275
  call_count = 0
280
276
  allow(Delayed::Job.connection).to receive(:execute).and_wrap_original do |m, (arg1, arg2)|
@@ -286,5 +282,20 @@ describe 'Delayed::Backed::ActiveRecord::Job' do
286
282
  expect(call_count).to eq 1
287
283
  expect(Delayed::Job.find(j.id)).to eq j
288
284
  end
285
+
286
+ it "does not lock a stranded failed job creation" do
287
+ j = create_job(strand: "test1")
288
+ # query for metadata to ensure it's loaded before we start mucking with the connection
289
+ Delayed::Backend::ActiveRecord::Job::Failed.new
290
+
291
+ allow(Delayed::Job.connection).to receive(:prepared_statements).and_return(false)
292
+ allow(Delayed::Job.connection).to receive(:execute).and_wrap_original do |original, *args|
293
+ expect(args.first).not_to include("pg_advisory_xact_lock")
294
+ original.call(*args)
295
+ end
296
+ allow(Delayed::Job.connection).to receive(:insert).never
297
+ j.fail!
298
+ allow(Delayed::Job.connection).to receive(:execute).and_call_original
299
+ end
289
300
  end
290
301
  end
@@ -27,15 +27,5 @@ RSpec.describe Delayed::Periodic do
27
27
  expect(instance).to_not be_nil
28
28
  expect(instance.enqueue_args[:singleton]).to eq("periodic: just a test")
29
29
  end
30
-
31
- it "uses no singleton if told to skip" do
32
- Delayed::Periodic.cron job_name, '*/10 * * * *', {singleton: false} do
33
- # no-op
34
- end
35
- instance = Delayed::Periodic.scheduled[job_name]
36
- expect(instance).to_not be_nil
37
- expect(instance.enqueue_args[:singleton]).to be_nil
38
- Delayed::Periodic.perform_audit!
39
- end
40
30
  end
41
31
  end
@@ -3,7 +3,7 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe Delayed::WorkQueue::ParentProcess::Client do
6
- let(:subject) { described_class.new(addrinfo) }
6
+ let(:subject) { described_class.new(addrinfo).tap(&:init) }
7
7
  let(:addrinfo) { double('Addrinfo') }
8
8
  let(:connection) { double('Socket') }
9
9
  let(:job) { Delayed::Job.new(locked_by: "worker_name") }
@@ -1,76 +1,63 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'spec_helper'
4
- require 'imperium'
5
4
 
6
5
  RSpec.describe Delayed::Worker::ConsulHealthCheck do
7
6
  let(:health_check) { Delayed::Worker::ConsulHealthCheck.new(worker_name: 'foobar') }
8
7
 
9
- # can't use a verifying double for the response because the methods we're
10
- # tryig to stub are actually on HTTP::Message
11
- let(:response) { double('Imperium::Response') }
12
- let(:agent_client) { instance_double(Imperium::Agent) }
13
-
14
- before do
15
- allow(Imperium::Agent).to receive(:default_client).and_return(agent_client)
16
- end
17
-
18
8
  describe '#initialize' do
19
- it 'must use the default agent client when the config is mostly empty' do
9
+ it 'must use a default service client when the config is mostly empty' do
20
10
  check = Delayed::Worker::ConsulHealthCheck.new(worker_name: 'foobar')
21
- expect(check.agent_client).to eq Imperium::Agent.default_client
11
+ expect(check.service_client.configuration.url.to_s).to eq 'http://localhost:8500'
22
12
  end
23
13
 
24
- it 'must create a new agent API client when the config has relevant keys set' do
14
+ it 'must create a new service API client when the config has relevant keys set' do
25
15
  check = Delayed::Worker::ConsulHealthCheck.new(worker_name: 'foobar', config: {url: 'http://consul.example.com:8500'})
26
- agent_client = check.agent_client
27
- expect(agent_client).to_not eq Imperium::Agent.default_client
28
- expect(agent_client.config.url.to_s).to eq 'http://consul.example.com:8500'
16
+ service_client = check.service_client
17
+ expect(service_client.configuration.url.to_s).to eq 'http://consul.example.com:8500'
29
18
  end
30
19
  end
31
20
 
32
21
  describe '#start' do
33
22
  it 'must register this process as a service with consul' do
34
- expect(response).to receive(:ok?).and_return(true)
35
- expect(agent_client).to receive(:register_service)
36
- .with(an_instance_of(Imperium::Service))
37
- .and_return(response)
23
+ stub = stub_request(:put, "localhost:8500/v1/agent/service/register")
24
+ .with(body: hash_including({id: 'foobar' }))
25
+
38
26
  health_check.start
27
+
28
+ expect(stub).to have_been_requested
39
29
  end
40
30
 
41
31
 
42
32
  it 'must supply a args style check' do
43
- allow(response).to receive(:ok?).and_return(true)
44
- allow(agent_client).to receive(:register_service) { |service|
45
- check = service.checks.first
46
- expect(check.args).to_not be_nil
47
- response
48
- }
33
+ stub = stub_request(:put, "localhost:8500/v1/agent/service/register")
34
+ .with(body: hash_including({check: WebMock::API.hash_including({args: anything})}))
35
+
49
36
  health_check.start
37
+
38
+ expect(stub).to have_been_requested
50
39
  end
51
40
 
52
41
  it 'must include the docker container id when the docker option is set to true' do
42
+ stub = stub_request(:put, "localhost:8500/v1/agent/service/register")
43
+ .with(body: hash_including({check: WebMock::API.hash_including({docker_container_id: anything})}))
44
+
53
45
  local_health_check = Delayed::Worker::ConsulHealthCheck.new(
54
46
  worker_name: 'foobar',
55
47
  config: {docker: true}
56
48
  )
57
- allow(response).to receive(:ok?).and_return(true)
58
- allow(agent_client).to receive(:register_service) { |service|
59
- check = service.checks.first
60
- expect(check.docker_container_id).to_not be_nil
61
- response
62
- }
63
49
  local_health_check.start
50
+
51
+ expect(stub).to have_been_requested
64
52
  end
65
53
  end
66
54
 
67
55
  describe '#stop' do
68
56
  it 'must deregister the service from consul' do
69
- allow(response).to receive(:ok?).and_return(true)
70
- expect(agent_client).to receive(:deregister_service)
71
- .with(health_check.worker_name)
72
- .and_return(response)
57
+ stub = stub_request(:put, "localhost:8500/v1/agent/service/deregister/foobar")
58
+
73
59
  health_check.stop
60
+ expect(stub).to have_been_requested
74
61
  end
75
62
  end
76
63
  end
@@ -1,7 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gemspec :path=>"../../"
3
+ gemspec :path => "../../"
4
4
 
5
5
  gem "rails", "~> 5.2.0"
6
- gem 'sinatra', "2.0.0.beta2"
7
- gem 'sinatra-contrib', "2.0.0.beta2"
6
+ gem 'sinatra', "~> 2.0"
7
+ gem 'sinatra-contrib', "~> 2.0"
@@ -1,7 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gemspec :path=>"../../"
3
+ gemspec :path => "../../"
4
4
 
5
5
  gem "rails", "~> 6.0.0"
6
- gem 'sinatra', "2.0.0.beta2"
7
- gem 'sinatra-contrib', "2.0.0.beta2"
6
+ gem 'sinatra', "~> 2.0"
7
+ gem 'sinatra-contrib', "~> 2.0"
@@ -0,0 +1,246 @@
1
+ PATH
2
+ remote: ../..
3
+ specs:
4
+ inst-jobs (2.3.1)
5
+ activerecord (>= 5.2)
6
+ activesupport (>= 5.2)
7
+ after_transaction_commit (>= 1.0, < 3)
8
+ debug_inspector (~> 1.0)
9
+ fugit (~> 1.3)
10
+ railties (>= 5.2)
11
+ redis (> 3.0)
12
+ redis-scripting (~> 1.0.1)
13
+
14
+ GEM
15
+ remote: https://rubygems.org/
16
+ specs:
17
+ actioncable (6.0.3.7)
18
+ actionpack (= 6.0.3.7)
19
+ nio4r (~> 2.0)
20
+ websocket-driver (>= 0.6.1)
21
+ actionmailbox (6.0.3.7)
22
+ actionpack (= 6.0.3.7)
23
+ activejob (= 6.0.3.7)
24
+ activerecord (= 6.0.3.7)
25
+ activestorage (= 6.0.3.7)
26
+ activesupport (= 6.0.3.7)
27
+ mail (>= 2.7.1)
28
+ actionmailer (6.0.3.7)
29
+ actionpack (= 6.0.3.7)
30
+ actionview (= 6.0.3.7)
31
+ activejob (= 6.0.3.7)
32
+ mail (~> 2.5, >= 2.5.4)
33
+ rails-dom-testing (~> 2.0)
34
+ actionpack (6.0.3.7)
35
+ actionview (= 6.0.3.7)
36
+ activesupport (= 6.0.3.7)
37
+ rack (~> 2.0, >= 2.0.8)
38
+ rack-test (>= 0.6.3)
39
+ rails-dom-testing (~> 2.0)
40
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
41
+ actiontext (6.0.3.7)
42
+ actionpack (= 6.0.3.7)
43
+ activerecord (= 6.0.3.7)
44
+ activestorage (= 6.0.3.7)
45
+ activesupport (= 6.0.3.7)
46
+ nokogiri (>= 1.8.5)
47
+ actionview (6.0.3.7)
48
+ activesupport (= 6.0.3.7)
49
+ builder (~> 3.1)
50
+ erubi (~> 1.4)
51
+ rails-dom-testing (~> 2.0)
52
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
53
+ activejob (6.0.3.7)
54
+ activesupport (= 6.0.3.7)
55
+ globalid (>= 0.3.6)
56
+ activemodel (6.0.3.7)
57
+ activesupport (= 6.0.3.7)
58
+ activerecord (6.0.3.7)
59
+ activemodel (= 6.0.3.7)
60
+ activesupport (= 6.0.3.7)
61
+ activestorage (6.0.3.7)
62
+ actionpack (= 6.0.3.7)
63
+ activejob (= 6.0.3.7)
64
+ activerecord (= 6.0.3.7)
65
+ marcel (~> 1.0.0)
66
+ activesupport (6.0.3.7)
67
+ concurrent-ruby (~> 1.0, >= 1.0.2)
68
+ i18n (>= 0.7, < 2)
69
+ minitest (~> 5.1)
70
+ tzinfo (~> 1.1)
71
+ zeitwerk (~> 2.2, >= 2.2.2)
72
+ addressable (2.7.0)
73
+ public_suffix (>= 2.0.2, < 5.0)
74
+ after_transaction_commit (2.2.2)
75
+ activerecord (>= 5.2)
76
+ builder (3.2.4)
77
+ bump (0.10.0)
78
+ byebug (11.1.3)
79
+ coderay (1.1.3)
80
+ concurrent-ruby (1.1.9)
81
+ crack (0.4.5)
82
+ rexml
83
+ crass (1.0.6)
84
+ database_cleaner (2.0.1)
85
+ database_cleaner-active_record (~> 2.0.0)
86
+ database_cleaner-active_record (2.0.0)
87
+ activerecord (>= 5.a)
88
+ database_cleaner-core (~> 2.0.0)
89
+ database_cleaner-core (2.0.1)
90
+ debug_inspector (1.1.0)
91
+ deep_merge (1.2.1)
92
+ diff-lcs (1.4.4)
93
+ diplomat (2.5.1)
94
+ deep_merge (~> 1.2)
95
+ faraday (>= 0.9)
96
+ erubi (1.10.0)
97
+ et-orbi (1.2.4)
98
+ tzinfo
99
+ faraday (1.4.1)
100
+ faraday-excon (~> 1.1)
101
+ faraday-net_http (~> 1.0)
102
+ faraday-net_http_persistent (~> 1.1)
103
+ multipart-post (>= 1.2, < 3)
104
+ ruby2_keywords (>= 0.0.4)
105
+ faraday-excon (1.1.0)
106
+ faraday-net_http (1.0.1)
107
+ faraday-net_http_persistent (1.1.0)
108
+ fugit (1.4.5)
109
+ et-orbi (~> 1.1, >= 1.1.8)
110
+ raabro (~> 1.4)
111
+ globalid (0.4.2)
112
+ activesupport (>= 4.2.0)
113
+ hashdiff (1.0.1)
114
+ i18n (1.8.10)
115
+ concurrent-ruby (~> 1.0)
116
+ loofah (2.10.0)
117
+ crass (~> 1.0.2)
118
+ nokogiri (>= 1.5.9)
119
+ mail (2.7.1)
120
+ mini_mime (>= 0.1.1)
121
+ marcel (1.0.1)
122
+ method_source (1.0.0)
123
+ mini_mime (1.1.0)
124
+ minitest (5.14.4)
125
+ multi_json (1.15.0)
126
+ multipart-post (2.1.1)
127
+ mustermann (1.1.1)
128
+ ruby2_keywords (~> 0.0.1)
129
+ nio4r (2.5.7)
130
+ nokogiri (1.11.7-x86_64-darwin)
131
+ racc (~> 1.4)
132
+ pg (1.2.3)
133
+ pry (0.14.1)
134
+ coderay (~> 1.1)
135
+ method_source (~> 1.0)
136
+ public_suffix (4.0.6)
137
+ raabro (1.4.0)
138
+ racc (1.5.2)
139
+ rack (2.2.3)
140
+ rack-protection (2.1.0)
141
+ rack
142
+ rack-test (1.1.0)
143
+ rack (>= 1.0, < 3)
144
+ rails (6.0.3.7)
145
+ actioncable (= 6.0.3.7)
146
+ actionmailbox (= 6.0.3.7)
147
+ actionmailer (= 6.0.3.7)
148
+ actionpack (= 6.0.3.7)
149
+ actiontext (= 6.0.3.7)
150
+ actionview (= 6.0.3.7)
151
+ activejob (= 6.0.3.7)
152
+ activemodel (= 6.0.3.7)
153
+ activerecord (= 6.0.3.7)
154
+ activestorage (= 6.0.3.7)
155
+ activesupport (= 6.0.3.7)
156
+ bundler (>= 1.3.0)
157
+ railties (= 6.0.3.7)
158
+ sprockets-rails (>= 2.0.0)
159
+ rails-dom-testing (2.0.3)
160
+ activesupport (>= 4.2.0)
161
+ nokogiri (>= 1.6)
162
+ rails-html-sanitizer (1.3.0)
163
+ loofah (~> 2.3)
164
+ railties (6.0.3.7)
165
+ actionpack (= 6.0.3.7)
166
+ activesupport (= 6.0.3.7)
167
+ method_source
168
+ rake (>= 0.8.7)
169
+ thor (>= 0.20.3, < 2.0)
170
+ rake (13.0.3)
171
+ redis (4.2.5)
172
+ redis-scripting (1.0.1)
173
+ redis (>= 3.0)
174
+ rexml (3.2.5)
175
+ rspec (3.10.0)
176
+ rspec-core (~> 3.10.0)
177
+ rspec-expectations (~> 3.10.0)
178
+ rspec-mocks (~> 3.10.0)
179
+ rspec-core (3.10.1)
180
+ rspec-support (~> 3.10.0)
181
+ rspec-expectations (3.10.1)
182
+ diff-lcs (>= 1.2.0, < 2.0)
183
+ rspec-support (~> 3.10.0)
184
+ rspec-mocks (3.10.2)
185
+ diff-lcs (>= 1.2.0, < 2.0)
186
+ rspec-support (~> 3.10.0)
187
+ rspec-support (3.10.2)
188
+ ruby2_keywords (0.0.4)
189
+ sinatra (2.1.0)
190
+ mustermann (~> 1.0)
191
+ rack (~> 2.2)
192
+ rack-protection (= 2.1.0)
193
+ tilt (~> 2.0)
194
+ sinatra-contrib (2.1.0)
195
+ multi_json
196
+ mustermann (~> 1.0)
197
+ rack-protection (= 2.1.0)
198
+ sinatra (= 2.1.0)
199
+ tilt (~> 2.0)
200
+ sprockets (4.0.2)
201
+ concurrent-ruby (~> 1.0)
202
+ rack (> 1, < 3)
203
+ sprockets-rails (3.2.2)
204
+ actionpack (>= 4.0)
205
+ activesupport (>= 4.0)
206
+ sprockets (>= 3.0.0)
207
+ thor (1.1.0)
208
+ thread_safe (0.3.6)
209
+ tilt (2.0.10)
210
+ timecop (0.9.4)
211
+ tzinfo (1.2.9)
212
+ thread_safe (~> 0.1)
213
+ webmock (3.13.0)
214
+ addressable (>= 2.3.6)
215
+ crack (>= 0.3.2)
216
+ hashdiff (>= 0.4.0, < 2.0.0)
217
+ websocket-driver (0.7.5)
218
+ websocket-extensions (>= 0.1.0)
219
+ websocket-extensions (0.1.5)
220
+ wwtd (1.4.1)
221
+ zeitwerk (2.4.2)
222
+
223
+ PLATFORMS
224
+ x86_64-darwin-20
225
+
226
+ DEPENDENCIES
227
+ bump
228
+ byebug
229
+ database_cleaner (~> 2.0)
230
+ database_cleaner-active_record (~> 2.0)
231
+ diplomat (~> 2.5.1)
232
+ inst-jobs!
233
+ pg
234
+ pry
235
+ rack-test
236
+ rails (~> 6.0.0)
237
+ rake
238
+ rspec (~> 3.10)
239
+ sinatra (~> 2.0)
240
+ sinatra-contrib (~> 2.0)
241
+ timecop (= 0.9.4)
242
+ webmock
243
+ wwtd (~> 1.4.0)
244
+
245
+ BUNDLED WITH
246
+ 2.2.17
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec :path => "../../"
4
+
5
+ gem "rails", "~> 6.1.0"
6
+ gem 'sinatra', "~> 2.0"
7
+ gem 'sinatra-contrib', "~> 2.0"
@@ -313,6 +313,13 @@ shared_examples_for 'a backend' do
313
313
  expect(second).to eq nil
314
314
  end
315
315
 
316
+ it "complains if you pass more than one strand-based option" do
317
+ expect { create_job(strand: 'a', n_strand: 'b') }.to raise_error(ArgumentError)
318
+ expect { create_job(strand: 'a', singleton: 'b') }.to raise_error(ArgumentError)
319
+ expect { create_job(n_strand: 'a', singleton: 'b') }.to raise_error(ArgumentError)
320
+ expect { create_job(strand: 'a', n_strand: 'b', singleton: 'c') }.to raise_error(ArgumentError)
321
+ end
322
+
316
323
  context 'singleton' do
317
324
  it "should create if there's no jobs on the strand" do
318
325
  @job = create_job(:singleton => 'myjobs')
@@ -21,7 +21,7 @@ shared_examples_for 'Delayed::Worker' do
21
21
 
22
22
  describe "running a job" do
23
23
  it "should not fail when running a job with a % in the name" do
24
- @job = "Some % Name here".delay(ignore_transaction: true).starts_with?("Some % Name")
24
+ @job = "Some % Name here".delay(ignore_transaction: true).start_with?("Some % Name")
25
25
  @worker.perform(@job)
26
26
  end
27
27
  end
data/spec/spec_helper.rb CHANGED
@@ -5,8 +5,9 @@ require 'delayed/testing'
5
5
 
6
6
  require 'database_cleaner'
7
7
  require 'rack/test'
8
- require 'test_after_commit' if ::Rails.version < '5'
9
8
  require 'timecop'
9
+ require 'webmock/rspec'
10
+
10
11
  require 'pry'
11
12
  require 'byebug'
12
13
 
@@ -19,6 +20,7 @@ RSpec.configure do |config|
19
20
  config.before(:suite) do
20
21
  DatabaseCleaner.strategy = :transaction
21
22
  DatabaseCleaner.clean_with(:truncation)
23
+ WebMock.disable_net_connect!
22
24
  end
23
25
 
24
26
  config.before(:each) do |example|
@@ -60,18 +62,8 @@ connection_config = {
60
62
  database: ENV['TEST_DB_DATABASE'],
61
63
  }
62
64
 
63
- if ::Rails.version < '5'
64
- class ActiveRecord::Migration
65
- class << self
66
- def [](_version); self; end
67
- end
68
- end
69
- end
70
-
71
65
  def migrate(file)
72
- if ::Rails.version < '5.2'
73
- ActiveRecord::Migrator.migrate(file)
74
- elsif ::Rails.version >= '6'
66
+ if ::Rails.version >= '6'
75
67
  ActiveRecord::MigrationContext.new(file, ActiveRecord::SchemaMigration).migrate
76
68
  else
77
69
  ActiveRecord::MigrationContext.new(file).migrate
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inst-jobs
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.3
4
+ version: 2.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Luetke
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-12-22 00:00:00.000000000 Z
12
+ date: 2021-07-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -17,28 +17,28 @@ dependencies:
17
17
  requirements:
18
18
  - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: '4.2'
20
+ version: '5.2'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
- version: '4.2'
27
+ version: '5.2'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: activesupport
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: '4.2'
34
+ version: '5.2'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
- version: '4.2'
41
+ version: '5.2'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: after_transaction_commit
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -65,14 +65,14 @@ dependencies:
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '4.2'
68
+ version: '5.2'
69
69
  type: :runtime
70
70
  prerelease: false
71
71
  version_requirements: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '4.2'
75
+ version: '5.2'
76
76
  - !ruby/object:Gem::Dependency
77
77
  name: redis
78
78
  requirement: !ruby/object:Gem::Requirement
@@ -121,14 +121,14 @@ dependencies:
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: 0.0.3
124
+ version: '1.0'
125
125
  type: :runtime
126
126
  prerelease: false
127
127
  version_requirements: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 0.0.3
131
+ version: '1.0'
132
132
  - !ruby/object:Gem::Dependency
133
133
  name: bump
134
134
  requirement: !ruby/object:Gem::Requirement
@@ -161,44 +161,58 @@ dependencies:
161
161
  name: database_cleaner
162
162
  requirement: !ruby/object:Gem::Requirement
163
163
  requirements:
164
- - - '='
164
+ - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: 1.6.1
166
+ version: '2.0'
167
167
  type: :development
168
168
  prerelease: false
169
169
  version_requirements: !ruby/object:Gem::Requirement
170
170
  requirements:
171
- - - '='
171
+ - - "~>"
172
172
  - !ruby/object:Gem::Version
173
- version: 1.6.1
173
+ version: '2.0'
174
174
  - !ruby/object:Gem::Dependency
175
- name: imperium
175
+ name: database_cleaner-active_record
176
176
  requirement: !ruby/object:Gem::Requirement
177
177
  requirements:
178
- - - ">="
178
+ - - "~>"
179
179
  - !ruby/object:Gem::Version
180
- version: 0.5.2
180
+ version: '2.0'
181
181
  type: :development
182
182
  prerelease: false
183
183
  version_requirements: !ruby/object:Gem::Requirement
184
184
  requirements:
185
- - - ">="
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '2.0'
188
+ - !ruby/object:Gem::Dependency
189
+ name: diplomat
190
+ requirement: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: 2.5.1
195
+ type: :development
196
+ prerelease: false
197
+ version_requirements: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
186
200
  - !ruby/object:Gem::Version
187
- version: 0.5.2
201
+ version: 2.5.1
188
202
  - !ruby/object:Gem::Dependency
189
203
  name: pg
190
204
  requirement: !ruby/object:Gem::Requirement
191
205
  requirements:
192
- - - "<"
206
+ - - ">="
193
207
  - !ruby/object:Gem::Version
194
- version: '1.0'
208
+ version: '0'
195
209
  type: :development
196
210
  prerelease: false
197
211
  version_requirements: !ruby/object:Gem::Requirement
198
212
  requirements:
199
- - - "<"
213
+ - - ">="
200
214
  - !ruby/object:Gem::Version
201
- version: '1.0'
215
+ version: '0'
202
216
  - !ruby/object:Gem::Dependency
203
217
  name: pry
204
218
  requirement: !ruby/object:Gem::Requirement
@@ -261,14 +275,14 @@ dependencies:
261
275
  requirements:
262
276
  - - "~>"
263
277
  - !ruby/object:Gem::Version
264
- version: 3.8.0
278
+ version: '3.10'
265
279
  type: :development
266
280
  prerelease: false
267
281
  version_requirements: !ruby/object:Gem::Requirement
268
282
  requirements:
269
283
  - - "~>"
270
284
  - !ruby/object:Gem::Version
271
- version: 3.8.0
285
+ version: '3.10'
272
286
  - !ruby/object:Gem::Dependency
273
287
  name: sinatra
274
288
  requirement: !ruby/object:Gem::Requirement
@@ -303,14 +317,28 @@ dependencies:
303
317
  requirements:
304
318
  - - '='
305
319
  - !ruby/object:Gem::Version
306
- version: 0.7.1
320
+ version: 0.9.4
307
321
  type: :development
308
322
  prerelease: false
309
323
  version_requirements: !ruby/object:Gem::Requirement
310
324
  requirements:
311
325
  - - '='
312
326
  - !ruby/object:Gem::Version
313
- version: 0.7.1
327
+ version: 0.9.4
328
+ - !ruby/object:Gem::Dependency
329
+ name: webmock
330
+ requirement: !ruby/object:Gem::Requirement
331
+ requirements:
332
+ - - ">="
333
+ - !ruby/object:Gem::Version
334
+ version: '0'
335
+ type: :development
336
+ prerelease: false
337
+ version_requirements: !ruby/object:Gem::Requirement
338
+ requirements:
339
+ - - ">="
340
+ - !ruby/object:Gem::Version
341
+ version: '0'
314
342
  - !ruby/object:Gem::Dependency
315
343
  name: wwtd
316
344
  requirement: !ruby/object:Gem::Requirement
@@ -422,11 +450,10 @@ files:
422
450
  - spec/delayed/worker/consul_health_check_spec.rb
423
451
  - spec/delayed/worker/health_check_spec.rb
424
452
  - spec/delayed/worker_spec.rb
425
- - spec/gemfiles/42.gemfile
426
- - spec/gemfiles/50.gemfile
427
- - spec/gemfiles/51.gemfile
428
453
  - spec/gemfiles/52.gemfile
429
454
  - spec/gemfiles/60.gemfile
455
+ - spec/gemfiles/60.gemfile.lock
456
+ - spec/gemfiles/61.gemfile
430
457
  - spec/migrate/20140924140513_add_story_table.rb
431
458
  - spec/redis_job_spec.rb
432
459
  - spec/sample_jobs.rb
@@ -464,11 +491,10 @@ test_files:
464
491
  - spec/sample_jobs.rb
465
492
  - spec/spec_helper.rb
466
493
  - spec/redis_job_spec.rb
494
+ - spec/gemfiles/60.gemfile.lock
495
+ - spec/gemfiles/61.gemfile
467
496
  - spec/gemfiles/60.gemfile
468
- - spec/gemfiles/42.gemfile
469
497
  - spec/gemfiles/52.gemfile
470
- - spec/gemfiles/50.gemfile
471
- - spec/gemfiles/51.gemfile
472
498
  - spec/shared_jobs_specs.rb
473
499
  - spec/shared/performable_method.rb
474
500
  - spec/shared/testing.rb
@@ -1,7 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gemspec :path=>"../../"
4
-
5
- gem "rails", "~> 4.2.5"
6
- gem "after_transaction_commit", "<2"
7
- gem 'test_after_commit', '0.4.1'
@@ -1,7 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gemspec :path=>"../../"
4
-
5
- gem "rails", "~> 5.0.0"
6
- gem 'sinatra', "2.0.0.beta2"
7
- gem 'sinatra-contrib', "2.0.0.beta2"
@@ -1,7 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gemspec :path=>"../../"
4
-
5
- gem "rails", "~> 5.1.0"
6
- gem 'sinatra', "2.0.0.beta2"
7
- gem 'sinatra-contrib', "2.0.0.beta2"