inst-jobs 2.3.1 → 2.4.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/db/migrate/20101216224513_create_delayed_jobs.rb +9 -7
- data/db/migrate/20110531144916_cleanup_delayed_jobs_indexes.rb +8 -13
- data/db/migrate/20110610213249_optimize_delayed_jobs.rb +8 -8
- data/db/migrate/20110831210257_add_delayed_jobs_next_in_strand.rb +25 -25
- data/db/migrate/20120510004759_delayed_jobs_delete_trigger_lock_for_update.rb +4 -8
- data/db/migrate/20120531150712_drop_psql_jobs_pop_fn.rb +1 -3
- data/db/migrate/20120607164022_delayed_jobs_use_advisory_locks.rb +11 -15
- data/db/migrate/20120607181141_index_jobs_on_locked_by.rb +1 -1
- data/db/migrate/20120608191051_add_jobs_run_at_index.rb +2 -2
- data/db/migrate/20120927184213_change_delayed_jobs_handler_to_text.rb +1 -1
- data/db/migrate/20140505215510_copy_failed_jobs_original_id.rb +2 -3
- data/db/migrate/20150807133223_add_max_concurrent_to_jobs.rb +9 -13
- data/db/migrate/20151210162949_improve_max_concurrent.rb +4 -8
- data/db/migrate/20161206323555_add_back_default_string_limits_jobs.rb +3 -2
- data/db/migrate/20181217155351_speed_up_max_concurrent_triggers.rb +13 -17
- data/db/migrate/20200330230722_add_id_to_get_delayed_jobs_index.rb +8 -8
- data/db/migrate/20200824222232_speed_up_max_concurrent_delete_trigger.rb +72 -77
- data/db/migrate/20200825011002_add_strand_order_override.rb +93 -97
- data/db/migrate/20210809145804_add_n_strand_index.rb +12 -0
- data/db/migrate/20210812210128_add_singleton_column.rb +200 -0
- data/db/migrate/20210917232626_add_delete_conflicting_singletons_before_unlock_trigger.rb +27 -0
- data/exe/inst_jobs +3 -2
- data/lib/delayed/backend/active_record.rb +204 -150
- data/lib/delayed/backend/base.rb +107 -77
- data/lib/delayed/batch.rb +11 -9
- data/lib/delayed/cli.rb +98 -84
- data/lib/delayed/core_ext/kernel.rb +4 -2
- data/lib/delayed/daemon.rb +70 -74
- data/lib/delayed/job_tracking.rb +26 -25
- data/lib/delayed/lifecycle.rb +27 -24
- data/lib/delayed/log_tailer.rb +17 -17
- data/lib/delayed/logging.rb +13 -16
- data/lib/delayed/message_sending.rb +43 -52
- data/lib/delayed/performable_method.rb +6 -8
- data/lib/delayed/periodic.rb +72 -65
- data/lib/delayed/plugin.rb +2 -4
- data/lib/delayed/pool.rb +198 -192
- data/lib/delayed/server/helpers.rb +6 -6
- data/lib/delayed/server.rb +51 -54
- data/lib/delayed/settings.rb +93 -81
- data/lib/delayed/testing.rb +21 -22
- data/lib/delayed/version.rb +1 -1
- data/lib/delayed/work_queue/in_process.rb +21 -17
- data/lib/delayed/work_queue/parent_process/client.rb +55 -53
- data/lib/delayed/work_queue/parent_process/server.rb +219 -208
- data/lib/delayed/work_queue/parent_process.rb +52 -53
- data/lib/delayed/worker/consul_health_check.rb +21 -19
- data/lib/delayed/worker/health_check.rb +29 -22
- data/lib/delayed/worker/null_health_check.rb +3 -1
- data/lib/delayed/worker/process_helper.rb +8 -9
- data/lib/delayed/worker.rb +271 -261
- data/lib/delayed/yaml_extensions.rb +12 -10
- data/lib/delayed_job.rb +37 -38
- data/lib/inst-jobs.rb +1 -1
- data/spec/active_record_job_spec.rb +129 -136
- data/spec/delayed/cli_spec.rb +7 -7
- data/spec/delayed/daemon_spec.rb +8 -8
- data/spec/delayed/message_sending_spec.rb +16 -9
- data/spec/delayed/periodic_spec.rb +13 -12
- data/spec/delayed/server_spec.rb +38 -38
- data/spec/delayed/settings_spec.rb +26 -25
- data/spec/delayed/work_queue/in_process_spec.rb +7 -7
- data/spec/delayed/work_queue/parent_process/client_spec.rb +16 -12
- data/spec/delayed/work_queue/parent_process/server_spec.rb +43 -40
- data/spec/delayed/work_queue/parent_process_spec.rb +21 -21
- data/spec/delayed/worker/consul_health_check_spec.rb +22 -22
- data/spec/delayed/worker/health_check_spec.rb +60 -52
- data/spec/delayed/worker_spec.rb +28 -25
- data/spec/sample_jobs.rb +45 -15
- data/spec/shared/delayed_batch.rb +74 -67
- data/spec/shared/delayed_method.rb +143 -102
- data/spec/shared/performable_method.rb +39 -38
- data/spec/shared/shared_backend.rb +550 -437
- data/spec/shared/testing.rb +14 -14
- data/spec/shared/worker.rb +155 -147
- data/spec/shared_jobs_specs.rb +13 -13
- data/spec/spec_helper.rb +46 -41
- metadata +79 -53
- data/lib/delayed/backend/redis/bulk_update.lua +0 -50
- data/lib/delayed/backend/redis/destroy_job.lua +0 -2
- data/lib/delayed/backend/redis/enqueue.lua +0 -29
- data/lib/delayed/backend/redis/fail_job.lua +0 -5
- data/lib/delayed/backend/redis/find_available.lua +0 -3
- data/lib/delayed/backend/redis/functions.rb +0 -59
- data/lib/delayed/backend/redis/get_and_lock_next_available.lua +0 -17
- data/lib/delayed/backend/redis/includes/jobs_common.lua +0 -203
- data/lib/delayed/backend/redis/job.rb +0 -528
- data/lib/delayed/backend/redis/set_running.lua +0 -5
- data/lib/delayed/backend/redis/tickle_strand.lua +0 -2
- data/spec/gemfiles/52.gemfile +0 -7
- data/spec/gemfiles/60.gemfile +0 -7
- data/spec/gemfiles/61.gemfile +0 -7
- data/spec/redis_job_spec.rb +0 -148
data/lib/delayed/daemon.rb
CHANGED
@@ -1,97 +1,93 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "fileutils"
|
4
4
|
|
5
5
|
module Delayed
|
6
|
-
# Daemon controls the parent proces that runs the Pool and monitors the Worker processes.
|
7
|
-
class Daemon
|
8
|
-
|
6
|
+
# Daemon controls the parent proces that runs the Pool and monitors the Worker processes.
|
7
|
+
class Daemon
|
8
|
+
attr_reader :pid_folder
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
def initialize(pid_folder)
|
11
|
+
@pid_folder = pid_folder
|
12
|
+
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
14
|
+
def status(print: true, pid: self.pid)
|
15
|
+
alive = pid && (Process.kill(0, pid) rescue false) && :running
|
16
|
+
alive ||= :draining if pid && Process.kill(0, -pid) rescue false
|
17
|
+
if alive
|
18
|
+
puts "Delayed jobs #{alive}, pool PID: #{pid}" if print
|
19
|
+
elsif print && print != :alive
|
20
|
+
puts "No delayed jobs pool running"
|
21
|
+
end
|
22
|
+
alive
|
21
23
|
end
|
22
|
-
alive
|
23
|
-
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
def daemonize!
|
26
|
+
FileUtils.mkdir_p(pid_folder)
|
27
|
+
puts "Daemonizing..."
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
exit if fork
|
30
|
+
Process.setsid
|
31
|
+
exit if fork
|
32
|
+
Process.setpgrp
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
lock_file.puts(Process.pid.to_s)
|
42
|
-
lock_file.flush
|
34
|
+
@daemon = true
|
35
|
+
lock_file = File.open(pid_file, "wb")
|
36
|
+
# someone else is already running; just exit
|
37
|
+
exit unless lock_file.flock(File::LOCK_EX | File::LOCK_NB)
|
38
|
+
at_exit { lock_file.flock(File::LOCK_UN) }
|
39
|
+
lock_file.puts(Process.pid.to_s)
|
40
|
+
lock_file.flush
|
43
41
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
42
|
+
# if we blow up so badly that we can't syslog the error, try to send
|
43
|
+
# it somewhere useful
|
44
|
+
last_ditch_logfile = Settings.last_ditch_logfile || "log/delayed_job.log"
|
45
|
+
last_ditch_logfile = Settings.expand_rails_path(last_ditch_logfile) if last_ditch_logfile[0] != "|"
|
46
|
+
$stdin.reopen("/dev/null")
|
47
|
+
$stdout.reopen(open(last_ditch_logfile, "a")) # rubocop:disable Security/Open
|
48
|
+
$stderr.reopen($stdout)
|
49
|
+
$stdout.sync = $stderr.sync = true
|
49
50
|
end
|
50
|
-
STDIN.reopen("/dev/null")
|
51
|
-
STDOUT.reopen(open(last_ditch_logfile, 'a'))
|
52
|
-
STDERR.reopen(STDOUT)
|
53
|
-
STDOUT.sync = STDERR.sync = true
|
54
|
-
end
|
55
51
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
52
|
+
# stop the currently running daemon (not this current process, the one in the pid_file)
|
53
|
+
def stop(kill: false, pid: self.pid)
|
54
|
+
alive = status(pid: pid, print: false)
|
55
|
+
if alive == :running || (kill && alive == :draining)
|
56
|
+
puts "Stopping pool #{pid}..."
|
57
|
+
signal = kill ? "TERM" : "QUIT"
|
58
|
+
begin
|
59
|
+
Process.kill(signal, pid)
|
60
|
+
rescue Errno::ESRCH
|
61
|
+
# ignore if the pid no longer exists
|
62
|
+
end
|
63
|
+
wait(kill)
|
64
|
+
else
|
65
|
+
status
|
66
66
|
end
|
67
|
-
wait(kill)
|
68
|
-
else
|
69
|
-
status
|
70
67
|
end
|
71
|
-
end
|
72
68
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
69
|
+
def wait(kill)
|
70
|
+
if kill
|
71
|
+
sleep(0.5) while status(pid: pid, print: false)
|
72
|
+
else
|
73
|
+
sleep(0.5) while status(pid: pid, print: false) == :running
|
74
|
+
end
|
78
75
|
end
|
79
|
-
end
|
80
76
|
|
81
|
-
|
82
|
-
|
83
|
-
|
77
|
+
def pid_file
|
78
|
+
File.join(pid_folder, "delayed_jobs_pool.pid")
|
79
|
+
end
|
84
80
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
81
|
+
def pid
|
82
|
+
if File.file?(pid_file)
|
83
|
+
pid = File.read(pid_file).to_i
|
84
|
+
pid = nil unless pid.positive?
|
85
|
+
end
|
86
|
+
pid
|
89
87
|
end
|
90
|
-
pid
|
91
|
-
end
|
92
88
|
|
93
|
-
|
94
|
-
|
89
|
+
def daemonized?
|
90
|
+
!!@daemon
|
91
|
+
end
|
95
92
|
end
|
96
93
|
end
|
97
|
-
end
|
data/lib/delayed/job_tracking.rb
CHANGED
@@ -1,33 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Delayed
|
4
|
-
# Used when a block of code wants to track what jobs are created,
|
5
|
-
# for instance in tests.
|
6
|
-
# Delayed::Job.track_jobs { ...block... } returns a JobTracking object
|
7
|
-
# Right now this just tracks created jobs, it could be expanded to track a
|
8
|
-
# lot more about what's going on in Delayed Jobs as it's needed.
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
4
|
+
# Used when a block of code wants to track what jobs are created,
|
5
|
+
# for instance in tests.
|
6
|
+
# Delayed::Job.track_jobs { ...block... } returns a JobTracking object
|
7
|
+
# Right now this just tracks created jobs, it could be expanded to track a
|
8
|
+
# lot more about what's going on in Delayed Jobs as it's needed.
|
9
|
+
JobTracking = Struct.new(:created) do
|
10
|
+
def self.track
|
11
|
+
@current_tracking = new
|
12
|
+
yield
|
13
|
+
tracking = @current_tracking
|
14
|
+
@current_tracking = nil
|
15
|
+
tracking
|
16
|
+
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
def self.job_created(job)
|
19
|
+
@current_tracking.try(:job_created, job)
|
20
|
+
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
@lock.synchronize { self.created << job }
|
25
|
-
end
|
22
|
+
def job_created(job)
|
23
|
+
return unless job
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
@lock.synchronize { created << job }
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
super
|
30
|
+
self.created = []
|
31
|
+
@lock = Mutex.new
|
32
|
+
end
|
31
33
|
end
|
32
34
|
end
|
33
|
-
end
|
data/lib/delayed/lifecycle.rb
CHANGED
@@ -1,29 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Delayed
|
4
|
-
class InvalidCallback <
|
4
|
+
class InvalidCallback < RuntimeError; end
|
5
5
|
|
6
6
|
class Lifecycle
|
7
7
|
EVENTS = {
|
8
|
-
:
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
18
|
-
}
|
8
|
+
error: %i[worker job exception],
|
9
|
+
exceptional_exit: %i[worker exception],
|
10
|
+
execute: [:worker],
|
11
|
+
invoke_job: [:job],
|
12
|
+
loop: [:worker],
|
13
|
+
perform: %i[worker job],
|
14
|
+
pop: [:worker],
|
15
|
+
retry: %i[worker job exception],
|
16
|
+
work_queue_pop: %i[work_queue worker_config],
|
17
|
+
check_for_work: [:work_queue]
|
18
|
+
}.freeze
|
19
19
|
|
20
20
|
def initialize
|
21
21
|
reset!
|
22
22
|
end
|
23
23
|
|
24
24
|
def reset!
|
25
|
-
@callbacks = EVENTS.keys.
|
26
|
-
|
25
|
+
@callbacks = EVENTS.keys.each_with_object({}) do |e, hash|
|
26
|
+
hash[e] = Callback.new
|
27
|
+
hash
|
28
|
+
end
|
29
|
+
Delayed::Worker.plugins.each(&:reset!)
|
27
30
|
end
|
28
31
|
|
29
32
|
def before(event, &block)
|
@@ -39,7 +42,7 @@ module Delayed
|
|
39
42
|
end
|
40
43
|
|
41
44
|
def run_callbacks(event, *args, &block)
|
42
|
-
missing_callback(event) unless @callbacks.
|
45
|
+
missing_callback(event) unless @callbacks.key?(event)
|
43
46
|
|
44
47
|
unless EVENTS[event].size == args.size
|
45
48
|
raise ArgumentError, "Callback #{event} expects #{EVENTS[event].size} parameter(s): #{EVENTS[event].join(', ')}"
|
@@ -50,15 +53,15 @@ module Delayed
|
|
50
53
|
|
51
54
|
private
|
52
55
|
|
53
|
-
|
54
|
-
|
56
|
+
def add(type, event, &block)
|
57
|
+
missing_callback(event) unless @callbacks.key?(event)
|
55
58
|
|
56
|
-
|
57
|
-
|
59
|
+
@callbacks[event].add(type, &block)
|
60
|
+
end
|
58
61
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
+
def missing_callback(event)
|
63
|
+
raise InvalidCallback, "Unknown callback event: #{event}"
|
64
|
+
end
|
62
65
|
end
|
63
66
|
|
64
67
|
class Callback
|
@@ -67,7 +70,7 @@ module Delayed
|
|
67
70
|
@after = []
|
68
71
|
|
69
72
|
# Identity proc. Avoids special cases when there is no existing around chain.
|
70
|
-
@around =
|
73
|
+
@around = ->(*args, &block) { block.call(*args) }
|
71
74
|
end
|
72
75
|
|
73
76
|
def execute(*args, &block)
|
@@ -85,7 +88,7 @@ module Delayed
|
|
85
88
|
@after << callback
|
86
89
|
when :around
|
87
90
|
chain = @around # use a local variable so that the current chain is closed over in the following lambda
|
88
|
-
@around =
|
91
|
+
@around = ->(*a, &block) { chain.call(*a) { |*b| callback.call(*b, &block) } }
|
89
92
|
else
|
90
93
|
raise InvalidCallback, "Invalid callback type: #{type}"
|
91
94
|
end
|
data/lib/delayed/log_tailer.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Delayed
|
4
|
-
class LogTailer
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
4
|
+
class LogTailer
|
5
|
+
def run
|
6
|
+
if Rails.logger.respond_to?(:log_path)
|
7
|
+
log_path = Rails.logger.log_path
|
8
|
+
elsif Rails.logger.instance_variable_get("@logdev").try(:instance_variable_get, "@dev").try(:path)
|
9
|
+
log_path = Rails.logger.instance_variable_get("@logdev").instance_variable_get("@dev").path
|
10
|
+
else
|
11
|
+
return
|
12
|
+
end
|
13
|
+
Rails.logger.auto_flushing = true if Rails.logger.respond_to?(:auto_flushing=)
|
14
|
+
Thread.new do
|
15
|
+
f = File.open(log_path, "r")
|
16
|
+
f.seek(0, IO::SEEK_END)
|
17
|
+
loop do
|
18
|
+
content = f.read
|
19
|
+
content.present? ? $stdout.print(content) : sleep(0.5)
|
20
|
+
end
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|
24
|
-
end
|
data/lib/delayed/logging.rb
CHANGED
@@ -1,30 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "date"
|
4
4
|
|
5
5
|
module Delayed
|
6
6
|
module Logging
|
7
|
-
TIMESTAMP_FORMAT =
|
7
|
+
TIMESTAMP_FORMAT = "%Y-%m-%dT%H:%M:%S.%6N"
|
8
8
|
private_constant :TIMESTAMP_FORMAT
|
9
9
|
|
10
|
-
FORMAT =
|
10
|
+
FORMAT = "%s - %s"
|
11
11
|
private_constant :FORMAT
|
12
12
|
|
13
|
-
|
14
13
|
def self.logger
|
15
14
|
return @logger if @logger
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|
15
|
+
|
16
|
+
@logger = if defined?(Rails.logger) && Rails.logger
|
17
|
+
Rails.logger
|
18
|
+
else
|
19
|
+
::Logger.new($stdout).tap do |logger|
|
20
|
+
logger.formatter = lambda { |_, time, _, msg|
|
21
|
+
format(FORMAT, time.strftime(TIMESTAMP_FORMAT), msg)
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
28
25
|
end
|
29
26
|
|
30
27
|
def logger
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
if ::Rails.env.test? || ::Rails.env.development?
|
4
|
-
require 'debug_inspector'
|
5
|
-
end
|
3
|
+
require "debug_inspector" if ::Rails.env.test? || ::Rails.env.development?
|
6
4
|
|
7
5
|
module Delayed
|
8
6
|
module MessageSending
|
@@ -14,12 +12,12 @@ module Delayed
|
|
14
12
|
@sender = sender
|
15
13
|
end
|
16
14
|
|
17
|
-
def method_missing(method, *args, **kwargs)
|
15
|
+
def method_missing(method, *args, **kwargs) # rubocop:disable Style/MissingRespondToMissing
|
18
16
|
# method doesn't exist? must be method_missing; assume private access
|
19
17
|
@sender = nil if !@sender.nil? &&
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
@object.methods.exclude?(method) &&
|
19
|
+
@object.protected_methods.exclude?(method) &&
|
20
|
+
@object.private_methods.exclude?(method)
|
23
21
|
|
24
22
|
sender_is_object = @sender == @object
|
25
23
|
sender_is_class = @sender.is_a?(@object.class)
|
@@ -33,51 +31,47 @@ module Delayed
|
|
33
31
|
end
|
34
32
|
|
35
33
|
if @synchronous
|
36
|
-
if @sender.nil? || sender_is_object || sender_is_class && @object.protected_methods.include?(method)
|
37
|
-
if kwargs.empty?
|
38
|
-
|
39
|
-
|
40
|
-
return @object.send(method, *args, **kwargs)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
if kwargs.empty?
|
45
|
-
return @object.public_send(method, *args)
|
46
|
-
else
|
47
|
-
return @object.public_send(method, *args, **kwargs)
|
34
|
+
if @sender.nil? || sender_is_object || (sender_is_class && @object.protected_methods.include?(method))
|
35
|
+
return @object.send(method, *args) if kwargs.empty?
|
36
|
+
|
37
|
+
return @object.send(method, *args, **kwargs)
|
48
38
|
end
|
39
|
+
|
40
|
+
return @object.public_send(method, *args) if kwargs.empty?
|
41
|
+
|
42
|
+
return @object.public_send(method, *args, **kwargs)
|
49
43
|
end
|
50
44
|
|
51
45
|
ignore_transaction = @enqueue_args.delete(:ignore_transaction)
|
52
46
|
on_failure = @enqueue_args.delete(:on_failure)
|
53
47
|
on_permanent_failure = @enqueue_args.delete(:on_permanent_failure)
|
54
|
-
|
48
|
+
unless ignore_transaction
|
55
49
|
# delay queuing up the job in another database until the results of the current
|
56
50
|
# transaction are visible
|
57
51
|
connection = @object.class.connection if @object.class.respond_to?(:connection)
|
58
52
|
connection ||= @object.connection if @object.respond_to?(:connection)
|
59
53
|
connection ||= ::ActiveRecord::Base.connection
|
60
54
|
|
61
|
-
if
|
55
|
+
if ::Delayed::Job != ::Delayed::Backend::ActiveRecord::Job || connection != ::Delayed::Job.connection
|
62
56
|
connection.after_transaction_commit do
|
63
57
|
::Delayed::Job.enqueue(::Delayed::PerformableMethod.new(@object, method,
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
58
|
+
args: args, kwargs: kwargs,
|
59
|
+
on_failure: on_failure,
|
60
|
+
on_permanent_failure: on_permanent_failure,
|
61
|
+
sender: @sender),
|
62
|
+
**@enqueue_args)
|
69
63
|
end
|
70
64
|
return nil
|
71
65
|
end
|
72
66
|
end
|
73
67
|
|
74
68
|
result = ::Delayed::Job.enqueue(::Delayed::PerformableMethod.new(@object, method,
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
69
|
+
args: args,
|
70
|
+
kwargs: kwargs,
|
71
|
+
on_failure: on_failure,
|
72
|
+
on_permanent_failure: on_permanent_failure,
|
73
|
+
sender: @sender),
|
74
|
+
**@enqueue_args)
|
81
75
|
result = nil unless ignore_transaction
|
82
76
|
result
|
83
77
|
end
|
@@ -85,10 +79,8 @@ module Delayed
|
|
85
79
|
|
86
80
|
def delay(sender: nil, **enqueue_args)
|
87
81
|
# support procs/methods as enqueue arguments
|
88
|
-
enqueue_args.each do |k,v|
|
89
|
-
if v.respond_to?(:call)
|
90
|
-
enqueue_args[k] = v.call(self)
|
91
|
-
end
|
82
|
+
enqueue_args.each do |k, v|
|
83
|
+
enqueue_args[k] = v.call(self) if v.respond_to?(:call)
|
92
84
|
end
|
93
85
|
|
94
86
|
sender ||= __calculate_sender_for_delay
|
@@ -103,33 +95,32 @@ module Delayed
|
|
103
95
|
end
|
104
96
|
|
105
97
|
module ClassMethods
|
106
|
-
KWARG_ARG_TYPES = %i
|
98
|
+
KWARG_ARG_TYPES = %i[key keyreq keyrest].freeze
|
107
99
|
private_constant :KWARG_ARG_TYPES
|
108
100
|
|
109
101
|
def handle_asynchronously(method_name, **enqueue_args)
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
if has_kwargs? method_name
|
102
|
+
visibility = if public_method_defined?(method_name)
|
103
|
+
:public
|
104
|
+
elsif private_method_defined?(method_name)
|
105
|
+
:private
|
106
|
+
else
|
107
|
+
:protected
|
108
|
+
end
|
109
|
+
|
110
|
+
if kwargs? method_name
|
121
111
|
generated_delayed_methods.class_eval do
|
122
|
-
define_method(method_name,
|
112
|
+
define_method(method_name, lambda do |*args, synchronous: false, **kwargs|
|
123
113
|
if synchronous
|
124
114
|
super(*args, **kwargs)
|
125
115
|
else
|
126
|
-
delay(sender: __calculate_sender_for_delay, **enqueue_args)
|
116
|
+
delay(sender: __calculate_sender_for_delay, **enqueue_args)
|
117
|
+
.method_missing(method_name, *args, synchronous: true, **kwargs)
|
127
118
|
end
|
128
119
|
end)
|
129
120
|
end
|
130
121
|
else
|
131
122
|
generated_delayed_methods.class_eval do
|
132
|
-
define_method(method_name,
|
123
|
+
define_method(method_name, lambda do |*args, synchronous: false|
|
133
124
|
if synchronous
|
134
125
|
super(*args)
|
135
126
|
else
|
@@ -150,7 +141,7 @@ module Delayed
|
|
150
141
|
end
|
151
142
|
end
|
152
143
|
|
153
|
-
def
|
144
|
+
def kwargs?(method_name)
|
154
145
|
original_arg_types = instance_method(method_name).parameters.map(&:first)
|
155
146
|
original_arg_types.any? { |arg_type| KWARG_ARG_TYPES.include?(arg_type) }
|
156
147
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Delayed
|
4
|
-
|
4
|
+
PerformableMethod = Struct.new(:object, :method, :args, :kwargs, :fail_cb, :permanent_fail_cb, :sender) do # rubocop:disable Lint/StructNewOverride
|
5
5
|
def initialize(object, method, args: [], kwargs: {}, on_failure: nil, on_permanent_failure: nil, sender: nil)
|
6
6
|
raise NoMethodError, "undefined method `#{method}' for #{object.inspect}" unless object.respond_to?(method, true)
|
7
7
|
|
@@ -35,18 +35,16 @@ module Delayed
|
|
35
35
|
sender_is_object = sender == object
|
36
36
|
sender_is_class = sender.is_a?(object.class)
|
37
37
|
|
38
|
-
if sender.nil? || sender_is_object || sender_is_class && object.protected_methods.include?(method)
|
38
|
+
if sender.nil? || sender_is_object || (sender_is_class && object.protected_methods.include?(method))
|
39
39
|
if kwargs.empty?
|
40
40
|
object.send(method, *args)
|
41
41
|
else
|
42
42
|
object.send(method, *args, **kwargs)
|
43
43
|
end
|
44
|
+
elsif kwargs.empty?
|
45
|
+
object.public_send(method, *args)
|
44
46
|
else
|
45
|
-
|
46
|
-
object.public_send(method, *args)
|
47
|
-
else
|
48
|
-
object.public_send(method, *args, **kwargs)
|
49
|
-
end
|
47
|
+
object.public_send(method, *args, **kwargs)
|
50
48
|
end
|
51
49
|
end
|
52
50
|
|
@@ -74,7 +72,7 @@ module Delayed
|
|
74
72
|
def full_name
|
75
73
|
obj_name = object.is_a?(ActiveRecord::Base) ? "#{object.class}.find(#{object.id}).#{method}" : display_name
|
76
74
|
kgs = kwargs || {}
|
77
|
-
kwargs_str = kgs.map { |(k, v)| ", #{k}: #{deep_de_ar_ize(v)}"}.join
|
75
|
+
kwargs_str = kgs.map { |(k, v)| ", #{k}: #{deep_de_ar_ize(v)}" }.join
|
78
76
|
"#{obj_name}(#{args.map { |a| deep_de_ar_ize(a) }.join(', ')}#{kwargs_str})"
|
79
77
|
end
|
80
78
|
end
|