delayed_job_master 2.0.3 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +31 -34
- data/.gitignore +0 -2
- data/CHANGELOG.md +13 -0
- data/README.md +46 -33
- data/delayed_job_master.gemspec +8 -5
- data/lib/delayed/master/callbacks.rb +37 -0
- data/lib/delayed/master/command.rb +28 -5
- data/lib/delayed/master/config.rb +51 -58
- data/lib/delayed/master/core.rb +146 -0
- data/lib/delayed/master/database.rb +72 -0
- data/lib/delayed/master/file_reopener.rb +18 -0
- data/lib/delayed/master/forker.rb +30 -19
- data/lib/delayed/master/job_checker.rb +91 -47
- data/lib/delayed/master/job_finder.rb +31 -0
- data/lib/delayed/master/job_listener.rb +31 -0
- data/lib/delayed/master/monitoring.rb +37 -36
- data/lib/delayed/master/postgresql/job_listener.rb +73 -0
- data/lib/delayed/master/postgresql/job_notifier.rb +45 -0
- data/lib/delayed/master/safe_array.rb +30 -0
- data/lib/delayed/master/signaler.rb +17 -7
- data/lib/delayed/master/sleep.rb +18 -0
- data/lib/delayed/master/worker/backend/active_record.rb +41 -0
- data/lib/delayed/master/worker/extension.rb +14 -0
- data/lib/delayed/master/worker/lifecycle.rb +10 -0
- data/lib/delayed/master/worker/plugins/all.rb +17 -0
- data/lib/delayed/master/worker/plugins/executor_wrapper.rb +23 -0
- data/lib/delayed/master/worker/plugins/memory_checker.rb +28 -0
- data/lib/delayed/master/worker/plugins/signal_handler.rb +35 -0
- data/lib/delayed/master/worker/plugins/status_notifier.rb +21 -0
- data/lib/delayed/master/worker/thread_pool.rb +64 -0
- data/lib/delayed/master/worker/thread_worker.rb +65 -0
- data/lib/delayed/master/worker.rb +8 -7
- data/lib/delayed/master/worker_setting.rb +72 -0
- data/lib/delayed/master.rb +7 -100
- data/lib/delayed_job_master/railtie.rb +16 -0
- data/lib/delayed_job_master/version.rb +5 -0
- data/lib/delayed_job_master.rb +15 -1
- data/lib/generators/delayed_job_master/templates/config.rb +14 -14
- data/lib/generators/delayed_job_master/templates/script +1 -1
- metadata +71 -17
- data/gemfiles/rails50.gemfile +0 -7
- data/gemfiles/rails51.gemfile +0 -7
- data/gemfiles/rails52.gemfile +0 -7
- data/lib/delayed/master/database_detector.rb +0 -37
- data/lib/delayed/master/job_counter.rb +0 -26
- data/lib/delayed/master/plugins/memory_checker.rb +0 -24
- data/lib/delayed/master/plugins/signal_handler.rb +0 -31
- data/lib/delayed/master/plugins/status_notifier.rb +0 -17
- data/lib/delayed/master/util/file_reopener.rb +0 -18
- data/lib/delayed/master/version.rb +0 -5
- data/lib/delayed/master/worker_extension.rb +0 -19
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Delayed
|
4
|
+
module Master
|
5
|
+
module Postgresql
|
6
|
+
class JobListener < Delayed::Master::JobListener
|
7
|
+
def initialize(master)
|
8
|
+
@master = master
|
9
|
+
@config = master.config
|
10
|
+
@databases = master.databases
|
11
|
+
@threads = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def start
|
15
|
+
@threads = @databases.map do |database|
|
16
|
+
Thread.new(database) do |database|
|
17
|
+
loop do
|
18
|
+
if @master.stop?
|
19
|
+
break
|
20
|
+
else
|
21
|
+
listen(database)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def wait
|
29
|
+
@threads.each(&:join)
|
30
|
+
end
|
31
|
+
|
32
|
+
def shutdown
|
33
|
+
@threads.each(&:kill)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def listen(database)
|
39
|
+
database.with_connection do |connection|
|
40
|
+
listen_connection(database, connection) do
|
41
|
+
loop do
|
42
|
+
if @master.stop?
|
43
|
+
break
|
44
|
+
else
|
45
|
+
wait_for_notify(database, connection)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def listen_connection(database, connection)
|
53
|
+
@master.logger.info { "listening @#{database.spec_name}..." }
|
54
|
+
connection.execute("LISTEN delayed_job_master")
|
55
|
+
yield
|
56
|
+
rescue => e
|
57
|
+
@master.logger.warn { "#{e.class}: #{e.message}" }
|
58
|
+
@master.logger.debug { e.backtrace.join("\n") }
|
59
|
+
ensure
|
60
|
+
@master.logger.info { "unlisten @#{database.spec_name}" }
|
61
|
+
connection.execute("UNLISTEN delayed_job_master")
|
62
|
+
end
|
63
|
+
|
64
|
+
def wait_for_notify(database, connection)
|
65
|
+
connection.raw_connection.wait_for_notify(1) do |_event, _pid, _payload|
|
66
|
+
@master.logger.info { "received notification @#{database.spec_name}" }
|
67
|
+
@master.job_checker.schedule(database)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Delayed
|
4
|
+
module Master
|
5
|
+
module Postgresql
|
6
|
+
class << self
|
7
|
+
def notify(model)
|
8
|
+
model.connection.execute "NOTIFY delayed_job_master"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module JobNotifier
|
13
|
+
extend ActiveSupport::Concern
|
14
|
+
|
15
|
+
included do
|
16
|
+
after_create :notify_to_delayed_job_master
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def notify_to_delayed_job_master
|
22
|
+
if run_at && run_at < Time.zone.now
|
23
|
+
Delayed::Master::Postgresql.notify(self.class)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module BulkJobNotifier
|
29
|
+
extend ActiveSupport::Concern
|
30
|
+
|
31
|
+
included do
|
32
|
+
after_enqueue :notify_to_delayed_job_master
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def notify_to_delayed_job_master
|
38
|
+
if @jobs.any? { |job| job.run_at && job.run_at < Time.zone.now }
|
39
|
+
Delayed::Master::Postgresql.notify(@jobs.first.class)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Delayed
|
4
|
+
module Master
|
5
|
+
class SafeArray < Array
|
6
|
+
def initialize(*args)
|
7
|
+
@mon = Monitor.new
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def <<(*args)
|
12
|
+
@mon.synchronize do
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def delete(*args)
|
18
|
+
@mon.synchronize do
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def clear
|
24
|
+
@mon.synchronize do
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,13 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Delayed
|
2
|
-
|
4
|
+
module Master
|
3
5
|
class Signaler
|
6
|
+
SIGNAL_HANDLERS = [
|
7
|
+
[:TERM, :stop],
|
8
|
+
[:INT, :stop],
|
9
|
+
[:QUIT, :quit],
|
10
|
+
[:WINCH, :graceful_stop],
|
11
|
+
[:USR1, :reopen_files],
|
12
|
+
[:USR2, :restart]
|
13
|
+
]
|
14
|
+
|
4
15
|
def initialize(master)
|
5
16
|
@master = master
|
6
17
|
end
|
7
18
|
|
8
19
|
def register
|
9
|
-
|
10
|
-
signals.each do |signal, method|
|
20
|
+
SIGNAL_HANDLERS.each do |signal, method|
|
11
21
|
register_signal(signal, method)
|
12
22
|
end
|
13
23
|
end
|
@@ -22,9 +32,9 @@ module Delayed
|
|
22
32
|
private
|
23
33
|
|
24
34
|
def register_signal(signal, method)
|
25
|
-
trap(signal) do
|
35
|
+
Signal.trap(signal) do
|
26
36
|
Thread.new do
|
27
|
-
@master.logger.info "received #{signal} signal"
|
37
|
+
@master.logger.info { "received #{signal} signal" }
|
28
38
|
@master.public_send(method)
|
29
39
|
end
|
30
40
|
end
|
@@ -32,9 +42,9 @@ module Delayed
|
|
32
42
|
|
33
43
|
def dispatch_to(signal, pid)
|
34
44
|
Process.kill(signal, pid)
|
35
|
-
@master.logger.info "sent #{signal} signal to worker #{pid}"
|
45
|
+
@master.logger.info { "sent #{signal} signal to worker #{pid}" }
|
36
46
|
rescue
|
37
|
-
@master.logger.error "failed to send #{signal} signal to worker #{pid}"
|
47
|
+
@master.logger.error { "failed to send #{signal} signal to worker #{pid}" }
|
38
48
|
end
|
39
49
|
end
|
40
50
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Delayed
|
4
|
+
module Master
|
5
|
+
module Sleep
|
6
|
+
def loop_with_sleep(sec)
|
7
|
+
count = [sec.to_i, 1].max
|
8
|
+
div = sec.to_f / count
|
9
|
+
loop do
|
10
|
+
count.times do |i|
|
11
|
+
yield i
|
12
|
+
sleep div
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Delayed
|
4
|
+
module Backend
|
5
|
+
module ActiveRecord
|
6
|
+
class Job < ::ActiveRecord::Base
|
7
|
+
# Remove locked_by from query because all jobs reserved by current process have same locked_by.
|
8
|
+
def self.ready_to_run(worker_name, max_run_time)
|
9
|
+
where(
|
10
|
+
"(run_at <= ? AND (locked_at IS NULL OR locked_at < ?)) AND failed_at IS NULL",
|
11
|
+
db_time_now,
|
12
|
+
db_time_now - max_run_time
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Patch for postgresql query.
|
17
|
+
def self.reserve_with_scope_using_optimized_postgres(ready_scope, worker, now)
|
18
|
+
quoted_name = connection.quote_table_name(table_name)
|
19
|
+
subquery = ready_scope.limit(1).lock(true).select("id").to_sql
|
20
|
+
sql = <<~SQL.squish
|
21
|
+
WITH job AS (#{subquery} SKIP LOCKED)
|
22
|
+
UPDATE #{quoted_name} AS jobs SET locked_at = ?, locked_by = ? FROM job
|
23
|
+
WHERE jobs.id = job.id RETURNING *
|
24
|
+
SQL
|
25
|
+
reserved = find_by_sql([sql, now, worker.name])
|
26
|
+
reserved[0]
|
27
|
+
end
|
28
|
+
|
29
|
+
# Patch for mysql query.
|
30
|
+
def self.reserve_with_scope_using_optimized_mysql(ready_scope, worker, now)
|
31
|
+
transaction do
|
32
|
+
ready_scope.limit(worker.read_ahead).select(:id).lock.detect do |job|
|
33
|
+
count = where(id: job.id).update_all(locked_at: now, locked_by: worker.name)
|
34
|
+
count == 1 && job.reload
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lifecycle'
|
4
|
+
require_relative 'thread_pool'
|
5
|
+
require_relative 'thread_worker'
|
6
|
+
require_relative 'plugins/all'
|
7
|
+
require_relative 'backend/active_record' if defined?(Delayed::Backend::ActiveRecord)
|
8
|
+
|
9
|
+
module Delayed
|
10
|
+
class Worker
|
11
|
+
attr_accessor :master_logger
|
12
|
+
attr_accessor :max_threads, :max_memory
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
events = Delayed::Lifecycle::EVENTS.dup.merge(
|
4
|
+
thread: [:worker],
|
5
|
+
scheduler_thread: [:worker],
|
6
|
+
worker_thread: [:worker, :job]
|
7
|
+
)
|
8
|
+
|
9
|
+
Delayed::Lifecycle.send(:remove_const, :EVENTS)
|
10
|
+
Delayed::Lifecycle.const_set(:EVENTS, events)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'executor_wrapper'
|
4
|
+
require_relative 'memory_checker'
|
5
|
+
require_relative 'signal_handler'
|
6
|
+
require_relative 'status_notifier'
|
7
|
+
|
8
|
+
[
|
9
|
+
Delayed::Master::Worker::Plugins::ExecutorWrapper,
|
10
|
+
Delayed::Master::Worker::Plugins::MemoryChecker,
|
11
|
+
Delayed::Master::Worker::Plugins::SignalHandler,
|
12
|
+
Delayed::Master::Worker::Plugins::StatusNotifier
|
13
|
+
].each do |plugin|
|
14
|
+
unless Delayed::Worker.plugins.include?(plugin)
|
15
|
+
Delayed::Worker.plugins << plugin
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Delayed
|
4
|
+
module Master
|
5
|
+
class Worker
|
6
|
+
module Plugins
|
7
|
+
class ExecutorWrapper < Delayed::Plugin
|
8
|
+
callbacks do |lifecycle|
|
9
|
+
lifecycle.around(:thread) do |worker, &block|
|
10
|
+
if defined?(Rails)
|
11
|
+
Rails.application.executor.wrap do
|
12
|
+
block.call
|
13
|
+
end
|
14
|
+
else
|
15
|
+
block.call
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'get_process_mem'
|
4
|
+
|
5
|
+
module Delayed
|
6
|
+
module Master
|
7
|
+
class Worker
|
8
|
+
module Plugins
|
9
|
+
class MemoryChecker < Delayed::Plugin
|
10
|
+
callbacks do |lifecycle|
|
11
|
+
lifecycle.before(:perform) do |worker, job|
|
12
|
+
mem = GetProcessMem.new
|
13
|
+
worker.master_logger.info { "performing #{job.name}, memory: #{mem.mb.to_i} MB" }
|
14
|
+
end
|
15
|
+
lifecycle.after(:perform) do |worker, job|
|
16
|
+
mem = GetProcessMem.new
|
17
|
+
worker.master_logger.info { "performed #{job.name}, memory: #{mem.mb.to_i} MB" }
|
18
|
+
if worker.max_memory && mem.mb > worker.max_memory
|
19
|
+
worker.master_logger.info { "shutting down worker #{Process.pid} because it consumes large memory..." }
|
20
|
+
worker.stop
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Delayed
|
4
|
+
module Master
|
5
|
+
class Worker
|
6
|
+
module Plugins
|
7
|
+
class SignalHandler < Delayed::Plugin
|
8
|
+
callbacks do |lifecycle|
|
9
|
+
lifecycle.before(:execute) do |worker|
|
10
|
+
worker.instance_eval do
|
11
|
+
Signal.trap(:USR1) do
|
12
|
+
Thread.new do
|
13
|
+
master_logger.info { "reopening files..." }
|
14
|
+
Delayed::Master::FileReopener.reopen
|
15
|
+
master_logger.info { "reopened" }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
Signal.trap(:USR2) do
|
19
|
+
Thread.new do
|
20
|
+
$0 = "#{$0} [OLD]"
|
21
|
+
master_logger.info { "shutting down worker #{Process.pid}..." }
|
22
|
+
stop
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
lifecycle.after(:execute) do |worker|
|
28
|
+
worker.master_logger.info { "shut down worker #{Process.pid}" }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Delayed
|
4
|
+
module Master
|
5
|
+
class Worker
|
6
|
+
module Plugins
|
7
|
+
class StatusNotifier < Delayed::Plugin
|
8
|
+
callbacks do |lifecycle|
|
9
|
+
lifecycle.around(:execute) do |worker, job, &block|
|
10
|
+
title = $0
|
11
|
+
$0 = "#{title} [BUSY]"
|
12
|
+
ret = block.call
|
13
|
+
$0 = title
|
14
|
+
ret
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Delayed
|
4
|
+
module Master
|
5
|
+
class Worker
|
6
|
+
class ThreadPool
|
7
|
+
def initialize(worker, size)
|
8
|
+
@worker = worker
|
9
|
+
@size = size
|
10
|
+
@queue = SizedQueue.new(@size)
|
11
|
+
@queue_delay = 0.5
|
12
|
+
end
|
13
|
+
|
14
|
+
def schedule
|
15
|
+
@scheduler = Thread.new do
|
16
|
+
Delayed::Worker.lifecycle.run_callbacks(:thread, @worker) do
|
17
|
+
loop do
|
18
|
+
while @queue.num_waiting == 0
|
19
|
+
sleep @queue_delay
|
20
|
+
end
|
21
|
+
|
22
|
+
if item = yield
|
23
|
+
@queue.push(item)
|
24
|
+
Thread.pass
|
25
|
+
else
|
26
|
+
@size.times { @queue.push(:exit) }
|
27
|
+
break
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def work
|
35
|
+
@threads = @size.times.map do
|
36
|
+
Thread.new do
|
37
|
+
Delayed::Worker.lifecycle.run_callbacks(:thread, @worker) do
|
38
|
+
loop do
|
39
|
+
item = @queue.pop
|
40
|
+
if item == :exit
|
41
|
+
break
|
42
|
+
else
|
43
|
+
yield item
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def wait
|
52
|
+
@scheduler.join
|
53
|
+
@threads.each(&:join)
|
54
|
+
end
|
55
|
+
|
56
|
+
def shutdown
|
57
|
+
@scheduler.kill
|
58
|
+
@threads.each(&:kill)
|
59
|
+
@queue.close
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Overrides Delayed::Worker to support multithread.
|
4
|
+
# See original code at https://github.com/collectiveidea/delayed_job/blob/master/lib/delayed/worker.rb
|
5
|
+
module Delayed
|
6
|
+
module Master
|
7
|
+
class Worker
|
8
|
+
module ThreadWorker
|
9
|
+
def work_off(num = 100)
|
10
|
+
if multithread?
|
11
|
+
work_off_for_multithread
|
12
|
+
else
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def multithread?
|
18
|
+
@max_threads.to_i > 1
|
19
|
+
end
|
20
|
+
|
21
|
+
def work_off_for_multithread
|
22
|
+
success = 0
|
23
|
+
failure = 0
|
24
|
+
|
25
|
+
monitor = Monitor.new
|
26
|
+
thread_pool = ThreadPool.new(self, @max_threads)
|
27
|
+
|
28
|
+
thread_pool.schedule do
|
29
|
+
self.class.lifecycle.run_callbacks(:scheduler_thread, self) do
|
30
|
+
if stop?
|
31
|
+
next nil
|
32
|
+
else
|
33
|
+
next reserve_job
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
thread_pool.work do |job|
|
39
|
+
@master_logger.debug { "start worker thread #{Thread.current.object_id}" }
|
40
|
+
self.class.lifecycle.run_callbacks(:worker_thread, self, job) do
|
41
|
+
case run_one_job(job)
|
42
|
+
when true
|
43
|
+
monitor.synchronize { success += 1 }
|
44
|
+
when false
|
45
|
+
monitor.synchronize { failure += 1 }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
@master_logger.debug { "stop worker thread #{Thread.current.object_id}" }
|
49
|
+
end
|
50
|
+
|
51
|
+
thread_pool.wait
|
52
|
+
thread_pool.shutdown
|
53
|
+
|
54
|
+
[success, failure]
|
55
|
+
end
|
56
|
+
|
57
|
+
def run_one_job(job)
|
58
|
+
self.class.lifecycle.run_callbacks(:perform, self, job) { run(job) }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
Delayed::Worker.prepend Delayed::Master::Worker::ThreadWorker
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Delayed
|
2
|
-
|
4
|
+
module Master
|
3
5
|
class Worker
|
4
|
-
attr_accessor :
|
6
|
+
attr_accessor :setting, :database
|
5
7
|
attr_accessor :pid, :instance
|
6
8
|
|
7
9
|
def initialize(attrs = {})
|
@@ -15,14 +17,13 @@ module Delayed
|
|
15
17
|
end
|
16
18
|
|
17
19
|
def info
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
str
|
20
|
+
strs = [@setting.worker_info]
|
21
|
+
strs << "@#{@database.spec_name}" if @database
|
22
|
+
strs.join(' ')
|
22
23
|
end
|
23
24
|
|
24
25
|
def process_title
|
25
|
-
"delayed_job
|
26
|
+
"delayed_job: #{info}"
|
26
27
|
end
|
27
28
|
end
|
28
29
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Delayed
|
4
|
+
module Master
|
5
|
+
class WorkerSetting
|
6
|
+
SIMPLE_CONFIGS = [:id, :max_processes, :max_threads, :max_memory,
|
7
|
+
:min_priority, :max_priority, :sleep_delay, :read_ahead, :exit_on_complete,
|
8
|
+
:max_attempts, :max_run_time, :destroy_failed_jobs]
|
9
|
+
ARRAY_CONFIGS = [:queues]
|
10
|
+
|
11
|
+
attr_accessor *SIMPLE_CONFIGS
|
12
|
+
attr_accessor *ARRAY_CONFIGS
|
13
|
+
|
14
|
+
def initialize(attrs = {})
|
15
|
+
@queues = []
|
16
|
+
@max_processes = 1
|
17
|
+
@max_threads = 1
|
18
|
+
@exit_on_complete = true
|
19
|
+
self.attributes = attrs
|
20
|
+
end
|
21
|
+
|
22
|
+
def attributes=(attrs = {})
|
23
|
+
attrs.each do |key, value|
|
24
|
+
send("#{key}=", value)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def worker_name
|
29
|
+
"worker[#{id}]"
|
30
|
+
end
|
31
|
+
|
32
|
+
def worker_info
|
33
|
+
strs = [worker_name]
|
34
|
+
strs << "(#{@queues.join(', ')})" if @queues.present?
|
35
|
+
strs.join(' ')
|
36
|
+
end
|
37
|
+
|
38
|
+
SIMPLE_CONFIGS.each do |key|
|
39
|
+
define_method(key) do |*args|
|
40
|
+
if args.size > 0
|
41
|
+
instance_variable_set("@#{key}", args[0])
|
42
|
+
else
|
43
|
+
instance_variable_get("@#{key}")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
ARRAY_CONFIGS.each do |key|
|
49
|
+
define_method(key) do |*args|
|
50
|
+
if args.size > 0
|
51
|
+
instance_variable_set("@#{key}", Array(args[0]))
|
52
|
+
else
|
53
|
+
instance_variable_get("@#{key}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def control(value = nil)
|
59
|
+
ActiveSupport::Deprecation.warn <<-TEXT.squish
|
60
|
+
deprecated 'control' setting was used. Remove it from your config file.
|
61
|
+
TEXT
|
62
|
+
end
|
63
|
+
|
64
|
+
def count(value = nil)
|
65
|
+
ActiveSupport::Deprecation.warn <<-TEXT.squish
|
66
|
+
deprecated 'count' setting was used. Use 'max_processes' instead.
|
67
|
+
TEXT
|
68
|
+
max_processes value
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|