ductwork 0.8.1 → 0.9.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 +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/ductwork/processes/job_worker.rb +32 -11
- data/lib/ductwork/processes/job_worker_runner.rb +42 -45
- data/lib/ductwork/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9edf0e9d07be90e39d099d4f2f9a65677b4b37144c8fa5c7d3d0a88ab81ed1a3
|
|
4
|
+
data.tar.gz: 91b2177670ee8333062ed6182512f4c5b2cd3ecfc3db9c36a77fcdf54397f65a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7583ac23a38875a63ac31b333348ddc9ec4e35b431ec90b335eb2580a241c508acbfcfdc462957a2ce39f5c7cb6094d146f60b8b4e49b753bfc0ead13967bcc4
|
|
7
|
+
data.tar.gz: 466d021eb4635d0d7ba284569100905069598f5c58edbdc3480e9db3d2de2ba09485b72935280598ac8223374cefebfa16b5d3c60a17709df9d2455a8c1273c5
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Ductwork Changelog
|
|
2
2
|
|
|
3
|
+
## [0.9.0]
|
|
4
|
+
|
|
5
|
+
- feat: add health check to job worker runner process - this is a basic check if a thread is healthy via `Thread#alive?` and restarts the thread if it is dead
|
|
6
|
+
|
|
3
7
|
## [0.8.1]
|
|
4
8
|
|
|
5
9
|
- fix: properly wrap "units of work" in rails application executor in pipeline advancer
|
|
@@ -3,18 +3,44 @@
|
|
|
3
3
|
module Ductwork
|
|
4
4
|
module Processes
|
|
5
5
|
class JobWorker
|
|
6
|
-
|
|
6
|
+
attr_reader :thread, :last_hearthbeat_at
|
|
7
|
+
|
|
8
|
+
def initialize(pipeline, id)
|
|
7
9
|
@pipeline = pipeline
|
|
8
|
-
@
|
|
10
|
+
@id = id
|
|
11
|
+
@running_context = Ductwork::RunningContext.new
|
|
12
|
+
@thread = nil
|
|
13
|
+
@last_hearthbeat_at = Time.current
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def start
|
|
17
|
+
@thread = Thread.new { work_loop }
|
|
18
|
+
@thread.name = "ductwork.job_worker.#{id}"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
alias restart start
|
|
22
|
+
|
|
23
|
+
def alive?
|
|
24
|
+
thread&.alive? || false
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def stop
|
|
28
|
+
running_context.shutdown!
|
|
9
29
|
end
|
|
10
30
|
|
|
11
|
-
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
attr_reader :pipeline, :id, :running_context
|
|
34
|
+
|
|
35
|
+
def work_loop
|
|
12
36
|
run_hooks_for(:start)
|
|
37
|
+
|
|
13
38
|
Ductwork.logger.debug(
|
|
14
39
|
msg: "Entering main work loop",
|
|
15
40
|
role: :job_worker,
|
|
16
41
|
pipeline: pipeline
|
|
17
42
|
)
|
|
43
|
+
|
|
18
44
|
while running_context.running?
|
|
19
45
|
Ductwork.logger.debug(
|
|
20
46
|
msg: "Attempting to claim job",
|
|
@@ -37,21 +63,16 @@ module Ductwork
|
|
|
37
63
|
)
|
|
38
64
|
sleep(polling_timeout)
|
|
39
65
|
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
shutdown
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
private
|
|
46
66
|
|
|
47
|
-
|
|
67
|
+
@last_hearthbeat_at = Time.current
|
|
68
|
+
end
|
|
48
69
|
|
|
49
|
-
def shutdown
|
|
50
70
|
Ductwork.logger.debug(
|
|
51
71
|
msg: "Shutting down",
|
|
52
72
|
role: :job_worker,
|
|
53
73
|
pipeline: pipeline
|
|
54
74
|
)
|
|
75
|
+
|
|
55
76
|
run_hooks_for(:stop)
|
|
56
77
|
end
|
|
57
78
|
|
|
@@ -6,7 +6,7 @@ module Ductwork
|
|
|
6
6
|
def initialize(pipeline)
|
|
7
7
|
@pipeline = pipeline
|
|
8
8
|
@running_context = Ductwork::RunningContext.new
|
|
9
|
-
@
|
|
9
|
+
@job_workers = []
|
|
10
10
|
|
|
11
11
|
Signal.trap(:INT) { running_context.shutdown! }
|
|
12
12
|
Signal.trap(:TERM) { running_context.shutdown! }
|
|
@@ -24,7 +24,9 @@ module Ductwork
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def run
|
|
27
|
-
|
|
27
|
+
create_process_record!
|
|
28
|
+
start_job_workers
|
|
29
|
+
|
|
28
30
|
Ductwork.logger.debug(
|
|
29
31
|
msg: "Entering main work loop",
|
|
30
32
|
role: :job_worker_runner,
|
|
@@ -34,7 +36,7 @@ module Ductwork
|
|
|
34
36
|
while running?
|
|
35
37
|
# TODO: Increase or make configurable
|
|
36
38
|
sleep(5)
|
|
37
|
-
|
|
39
|
+
check_thread_health
|
|
38
40
|
report_heartbeat!
|
|
39
41
|
end
|
|
40
42
|
|
|
@@ -43,43 +45,29 @@ module Ductwork
|
|
|
43
45
|
|
|
44
46
|
private
|
|
45
47
|
|
|
46
|
-
attr_reader :pipeline, :running_context, :
|
|
48
|
+
attr_reader :pipeline, :running_context, :job_workers
|
|
47
49
|
|
|
48
|
-
def
|
|
49
|
-
Ductwork.
|
|
50
|
+
def create_process_record!
|
|
51
|
+
Ductwork.wrap_with_app_executor do
|
|
52
|
+
Ductwork::Process.create!(
|
|
53
|
+
pid: ::Process.pid,
|
|
54
|
+
machine_identifier: Ductwork::MachineIdentifier.fetch,
|
|
55
|
+
last_heartbeat_at: Time.current
|
|
56
|
+
)
|
|
57
|
+
end
|
|
50
58
|
end
|
|
51
59
|
|
|
52
|
-
def
|
|
53
|
-
|
|
54
|
-
Ductwork.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
pipeline: pipeline
|
|
58
|
-
)
|
|
59
|
-
thread = Thread.new do
|
|
60
|
-
Ductwork::Processes::JobWorker
|
|
61
|
-
.new(pipeline, running_context)
|
|
62
|
-
.run
|
|
63
|
-
end
|
|
64
|
-
thread.name = "ductwork.job_worker.#{i}"
|
|
60
|
+
def start_job_workers
|
|
61
|
+
Ductwork.configuration.job_worker_count(pipeline).times do |i|
|
|
62
|
+
job_worker = Ductwork::Processes::JobWorker.new(pipeline, i)
|
|
63
|
+
job_workers.push(job_worker)
|
|
64
|
+
job_worker.start
|
|
65
65
|
|
|
66
66
|
Ductwork.logger.debug(
|
|
67
|
-
msg: "Created new
|
|
67
|
+
msg: "Created new job worker",
|
|
68
68
|
role: :job_worker_runner,
|
|
69
69
|
pipeline: pipeline
|
|
70
70
|
)
|
|
71
|
-
|
|
72
|
-
thread
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def create_process!
|
|
77
|
-
Ductwork.wrap_with_app_executor do
|
|
78
|
-
Ductwork::Process.create!(
|
|
79
|
-
pid: ::Process.pid,
|
|
80
|
-
machine_identifier: Ductwork::MachineIdentifier.fetch,
|
|
81
|
-
last_heartbeat_at: Time.current
|
|
82
|
-
)
|
|
83
71
|
end
|
|
84
72
|
end
|
|
85
73
|
|
|
@@ -87,13 +75,17 @@ module Ductwork
|
|
|
87
75
|
running_context.running?
|
|
88
76
|
end
|
|
89
77
|
|
|
90
|
-
def
|
|
78
|
+
def check_thread_health
|
|
91
79
|
Ductwork.logger.debug(
|
|
92
80
|
msg: "Attempting to synchronize threads",
|
|
93
81
|
role: :job_worker_runner,
|
|
94
82
|
pipeline: pipeline
|
|
95
83
|
)
|
|
96
|
-
|
|
84
|
+
job_workers.each do |job_worker|
|
|
85
|
+
if !job_worker.alive?
|
|
86
|
+
job_worker.restart
|
|
87
|
+
end
|
|
88
|
+
end
|
|
97
89
|
Ductwork.logger.debug(
|
|
98
90
|
msg: "Synchronizing threads timed out",
|
|
99
91
|
role: :job_worker_runner,
|
|
@@ -111,31 +103,36 @@ module Ductwork
|
|
|
111
103
|
|
|
112
104
|
def shutdown!
|
|
113
105
|
running_context.shutdown!
|
|
106
|
+
job_workers.each(&:stop)
|
|
114
107
|
await_threads_graceful_shutdown
|
|
115
|
-
|
|
116
|
-
|
|
108
|
+
kill_remaining_job_workers
|
|
109
|
+
delete_process_record!
|
|
117
110
|
end
|
|
118
111
|
|
|
119
112
|
def await_threads_graceful_shutdown
|
|
120
113
|
timeout = Ductwork.configuration.job_worker_shutdown_timeout
|
|
121
114
|
deadline = Time.current + timeout
|
|
122
115
|
|
|
123
|
-
Ductwork.logger.debug(
|
|
124
|
-
|
|
125
|
-
|
|
116
|
+
Ductwork.logger.debug(
|
|
117
|
+
msg: "Attempting graceful shutdown",
|
|
118
|
+
role: :job_worker_runner
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
while Time.current < deadline && job_workers.any?(&:alive?)
|
|
122
|
+
job_workers.each do |job_worker|
|
|
126
123
|
break if Time.current < deadline
|
|
127
124
|
|
|
128
125
|
# TODO: Maybe make this configurable. If there's a ton of workers
|
|
129
126
|
# it may not even get to the "later" ones depending on the timeout
|
|
130
|
-
thread.join(1)
|
|
127
|
+
job_worker.thread.join(1)
|
|
131
128
|
end
|
|
132
129
|
end
|
|
133
130
|
end
|
|
134
131
|
|
|
135
|
-
def
|
|
136
|
-
|
|
137
|
-
if
|
|
138
|
-
thread.kill
|
|
132
|
+
def kill_remaining_job_workers
|
|
133
|
+
job_workers.each do |job_worker|
|
|
134
|
+
if job_worker.alive?
|
|
135
|
+
job_worker.thread.kill
|
|
139
136
|
Ductwork.logger.debug(
|
|
140
137
|
msg: "Killed thread",
|
|
141
138
|
role: :job_worker_runner,
|
|
@@ -145,7 +142,7 @@ module Ductwork
|
|
|
145
142
|
end
|
|
146
143
|
end
|
|
147
144
|
|
|
148
|
-
def
|
|
145
|
+
def delete_process_record!
|
|
149
146
|
Ductwork.wrap_with_app_executor do
|
|
150
147
|
Ductwork::Process.find_by!(
|
|
151
148
|
pid: ::Process.pid,
|
data/lib/ductwork/version.rb
CHANGED