postjob 0.5.5 → 0.5.6
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/lib/postjob/cli/cron.rb +16 -0
- data/lib/postjob/cli/enqueue.rb +14 -0
- data/lib/postjob/cli/job.rb +15 -19
- data/lib/postjob/cli/ps.rb +8 -2
- data/lib/postjob/host.rb +41 -0
- data/lib/postjob/job.rb +23 -23
- data/lib/postjob/migrations/006_enqueue.sql +48 -4
- data/lib/postjob/migrations/006a_processing.sql +5 -2
- data/lib/postjob/migrations/007_job_results.sql +6 -5
- data/lib/postjob/migrations/008a_childjobs.sql +33 -38
- data/lib/postjob/migrations/010_settings.sql +1 -1
- data/lib/postjob/migrations/{008_checkout_runnable.sql → 013a_checkout_runnable.sql} +11 -7
- data/lib/postjob/migrations/017_zombie_check.sql +11 -6
- data/lib/postjob/migrations/021_cron_jobs.sql +65 -0
- data/lib/postjob/migrations/023_sticky_jobs.sql +16 -0
- data/lib/postjob/migrations.rb +3 -1
- data/lib/postjob/queue.rb +23 -4
- data/lib/postjob/record.rb +4 -10
- data/lib/postjob/registry.rb +117 -20
- data/lib/postjob/runner.rb +169 -166
- data/lib/postjob/worker_session.rb +9 -25
- data/lib/postjob/workflow.rb +26 -50
- data/lib/postjob.rb +97 -23
- data/lib/tools/heartbeat.rb +2 -2
- data/lib/tools/history.rb +1 -1
- data/spec/postjob/enqueue_spec.rb +3 -0
- data/spec/postjob/events/heartbeat_event_spec.rb +5 -67
- data/spec/postjob/events/zombie_event_spec.rb +61 -0
- data/spec/postjob/worker_session_spec.rb +1 -24
- data/spec/spec_helper.rb +1 -1
- data/spec/support/configure_active_record.rb +7 -16
- data/spec/support/configure_database.rb +11 -0
- data/spec/support/configure_simple_sql.rb +0 -16
- metadata +10 -5
- data/lib/tools/atomic_store.rb +0 -17
data/lib/postjob/workflow.rb
CHANGED
@@ -1,56 +1,32 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
#
|
1
|
+
# This module defines the interface available for workflow modules.
|
2
|
+
#
|
3
|
+
# This module is extended into the actual workflow module during registering.
|
4
4
|
module Postjob::Workflow
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
# include Postjob::Workflow
|
21
|
-
# def self.run(arg); ..; end
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# We therefore do not make this test here.
|
25
|
-
job.extend JobMethods
|
5
|
+
# Note: we would like to sure that there is a public run method, and we could
|
6
|
+
# inspect the module with a +extended+ callback. This, however, is only
|
7
|
+
# possible when the run method is already defined. So, with a job definition
|
8
|
+
# of
|
9
|
+
#
|
10
|
+
# module Foo
|
11
|
+
# include Postjob::Workflow
|
12
|
+
# def self.run(arg); ..; end
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# we cannot run such a test.
|
16
|
+
|
17
|
+
# see Postjob::Runner.async
|
18
|
+
def async(runner, *args, timeout: nil, max_attempts: nil)
|
19
|
+
::Postjob::Runner.async(runner, *args, timeout: timeout, max_attempts: max_attempts)
|
26
20
|
end
|
27
21
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
def await(job, *args, timeout: nil, max_attempts: nil)
|
34
|
-
::Postjob::Runner.await(job, *args, timeout: timeout, max_attempts: max_attempts)
|
35
|
-
end
|
36
|
-
|
37
|
-
def workflow_token(job)
|
38
|
-
expect! job.parent_id => ::Postjob::Runner.current_job.id
|
39
|
-
::Postjob::Queue.find_or_create_token(job)
|
40
|
-
end
|
41
|
-
|
42
|
-
def workflow_version
|
43
|
-
@workflow_version || "0.0"
|
44
|
-
end
|
45
|
-
|
46
|
-
def workflow_name
|
47
|
-
"#{name}@#{workflow_version}"
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
22
|
+
# see Postjob::Runner.await
|
23
|
+
def await(job, *args, timeout: nil, max_attempts: nil)
|
24
|
+
::Postjob::Runner.await(job, *args, timeout: timeout, max_attempts: max_attempts)
|
25
|
+
end
|
51
26
|
|
52
|
-
|
53
|
-
|
54
|
-
|
27
|
+
# see Postjob::Runner.workflow_token
|
28
|
+
def workflow_token(job)
|
29
|
+
expect! job.parent_id => ::Postjob::Runner.current_job.id
|
30
|
+
::Postjob::Queue.find_or_create_token(job)
|
55
31
|
end
|
56
32
|
end
|
data/lib/postjob.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# rubocop:disable Metrics/ParameterLists
|
2
2
|
# rubocop:disable Metrics/MethodLength
|
3
|
+
# rubocop:disable Metrics/ModuleLength
|
4
|
+
# rubocop:disable Metrics/AbcSize
|
5
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
6
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
3
7
|
|
4
8
|
require "expectation"
|
5
9
|
require "simple/sql"
|
@@ -13,6 +17,7 @@ require_relative "postjob/workflow"
|
|
13
17
|
require_relative "postjob/registry"
|
14
18
|
require_relative "postjob/job"
|
15
19
|
require_relative "postjob/worker_session"
|
20
|
+
require_relative "postjob/host"
|
16
21
|
require_relative "postjob/error"
|
17
22
|
require_relative "postjob/queue"
|
18
23
|
require_relative "postjob/runner"
|
@@ -21,26 +26,46 @@ module Postjob
|
|
21
26
|
attr_accessor :logger
|
22
27
|
extend self
|
23
28
|
|
29
|
+
def host_id
|
30
|
+
Host.host_id
|
31
|
+
end
|
32
|
+
|
24
33
|
# In fast mode <tt>Postjob.run</tt> doesn't wait that long between retrying
|
25
34
|
# failed jobs. This mode is enabled by default during tests; and it can be
|
26
35
|
# enabled via "postjob run --fast"
|
27
36
|
#
|
28
37
|
# Note that fast mode should only be used during development and tests.
|
29
|
-
attr_accessor :fast_mode
|
38
|
+
attr_accessor :fast_mode # :nodoc:
|
30
39
|
self.fast_mode = false
|
31
40
|
|
41
|
+
# Enqueues a workflow.
|
42
|
+
#
|
43
|
+
# Options include
|
44
|
+
#
|
45
|
+
# - version
|
46
|
+
# - max_attempts
|
47
|
+
# - timeout
|
48
|
+
# - sticky
|
49
|
+
# - cron_interval
|
50
|
+
# - queue
|
51
|
+
#
|
32
52
|
def enqueue!(workflow, *args, queue: nil,
|
33
53
|
parent_id: nil,
|
34
54
|
max_attempts: nil,
|
35
55
|
timeout: nil,
|
36
56
|
version: nil,
|
37
|
-
tags: nil
|
57
|
+
tags: nil,
|
58
|
+
cron_interval: nil,
|
59
|
+
sticky: nil)
|
38
60
|
expect! queue => [nil, String]
|
39
61
|
expect! workflow => String
|
40
62
|
expect! parent_id => [nil, Integer]
|
41
63
|
expect! max_attempts => [nil, Integer]
|
42
64
|
expect! timeout => [nil, Numeric]
|
43
65
|
expect! tags => [nil, Hash]
|
66
|
+
expect! sticky => [nil, false, true]
|
67
|
+
|
68
|
+
# -- prepare arguments ----------------------------------------------------
|
44
69
|
|
45
70
|
if workflow == "__manual__" && max_attempts != 1
|
46
71
|
if parent_id
|
@@ -52,13 +77,40 @@ module Postjob
|
|
52
77
|
max_attempts = 1
|
53
78
|
end
|
54
79
|
|
80
|
+
# -- fetch defaults from registry -----------------------------------------
|
81
|
+
|
82
|
+
spec = Postjob::Registry[workflow]
|
83
|
+
if spec
|
84
|
+
max_attempts = spec.options.max_attempts if max_attempts.nil?
|
85
|
+
timeout = spec.options.timeout if timeout.nil?
|
86
|
+
sticky = spec.options.sticky if sticky.nil?
|
87
|
+
cron_interval = spec.options.cron_interval if cron_interval.nil?
|
88
|
+
queue = spec.options.queue if queue.nil?
|
89
|
+
end
|
90
|
+
|
91
|
+
if cron_interval && cron_interval < 300
|
92
|
+
raise "cron interval must be at least 5 minutes"
|
93
|
+
end
|
94
|
+
|
95
|
+
# -- disable existing cron jobs -------------------------------------------
|
96
|
+
|
97
|
+
if cron_interval
|
98
|
+
Queue.disable_cron_jobs(workflow, args)
|
99
|
+
end
|
100
|
+
|
101
|
+
# -- enqueue jobs ---------------------------------------------------------
|
102
|
+
|
55
103
|
tags = stringify_hash(tags) if tags
|
104
|
+
|
56
105
|
job = Queue.enqueue_job current_worker_session.id, workflow, *args, queue: queue,
|
57
106
|
parent_id: parent_id,
|
58
107
|
max_attempts: max_attempts,
|
59
108
|
timeout: timeout,
|
60
109
|
tags: tags,
|
61
|
-
version: version
|
110
|
+
version: version,
|
111
|
+
cron_interval: cron_interval,
|
112
|
+
sticky: sticky
|
113
|
+
|
62
114
|
logger.info "Generated process #{job}"
|
63
115
|
job.id
|
64
116
|
end
|
@@ -147,7 +199,48 @@ module Postjob
|
|
147
199
|
# This method connects to the queue. This means it registers as a new worker_session,
|
148
200
|
# if there was no worker_session yet.
|
149
201
|
def current_worker_session
|
150
|
-
@worker_session ||=
|
202
|
+
@worker_session ||= begin
|
203
|
+
WorkerSession.start!(Registry.runnable_workflows_with_versions)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# Explicitely resolve a workflow.
|
208
|
+
def resolve(token:, result:)
|
209
|
+
job = Queue.find_job_by_token(token)
|
210
|
+
raise "No job with token #{token}" unless job
|
211
|
+
|
212
|
+
Queue.set_job_result current_worker_session.id, job, result, version: nil
|
213
|
+
end
|
214
|
+
|
215
|
+
# Registers a workflow.
|
216
|
+
#
|
217
|
+
# This call registers a workflow with a set of options.
|
218
|
+
#
|
219
|
+
# This is usually used via
|
220
|
+
#
|
221
|
+
#
|
222
|
+
# module X
|
223
|
+
# Postjob.register self, max_attempts: 2, timeout: 86400
|
224
|
+
# end
|
225
|
+
#
|
226
|
+
#
|
227
|
+
# The +workflow+ parameter is either a module which implements a workflow,
|
228
|
+
# or a String with the name of a workflow, and a set of options.
|
229
|
+
#
|
230
|
+
# Options include
|
231
|
+
#
|
232
|
+
# - version
|
233
|
+
# - max_attempts
|
234
|
+
# - timeout
|
235
|
+
# - sticky
|
236
|
+
# - cron_interval
|
237
|
+
# - queue
|
238
|
+
#
|
239
|
+
def register_workflow(workflow, options = {})
|
240
|
+
expect! workflow => [ Module, String ]
|
241
|
+
|
242
|
+
workflow.extend Postjob::Workflow if workflow.is_a?(Module)
|
243
|
+
Registry.register workflow, options
|
151
244
|
end
|
152
245
|
|
153
246
|
private
|
@@ -177,23 +270,4 @@ module Postjob
|
|
177
270
|
|
178
271
|
shutdown
|
179
272
|
end
|
180
|
-
|
181
|
-
public
|
182
|
-
|
183
|
-
def resolve(token:, result:)
|
184
|
-
job = Queue.find_job_by_token(token)
|
185
|
-
raise "No job with token #{token}" unless job
|
186
|
-
|
187
|
-
Queue.set_job_result current_worker_session.id, job, result, version: nil
|
188
|
-
end
|
189
|
-
|
190
|
-
def register_workflow(workflow, options = {})
|
191
|
-
expect! options => {
|
192
|
-
version: [nil, /^\d+(\.\d+)*/]
|
193
|
-
}
|
194
|
-
|
195
|
-
workflow.include Postjob::Workflow
|
196
|
-
workflow.send(:set_workflow_version, options[:version] || "0.0")
|
197
|
-
Registry.register workflow, options
|
198
|
-
end
|
199
273
|
end
|
data/lib/tools/heartbeat.rb
CHANGED
@@ -26,7 +26,7 @@ require "vmstat/task"
|
|
26
26
|
# and yields current measurements once a second.
|
27
27
|
#
|
28
28
|
#
|
29
|
-
module Heartbeat
|
29
|
+
module Heartbeat # :nodoc:
|
30
30
|
# The heartbeat monitor watches various machine metrics (disk usage, CPU load, network traffic)
|
31
31
|
# and yields current measurements once every cycle_length_seconds seconds.
|
32
32
|
|
@@ -62,7 +62,7 @@ module Heartbeat
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
class Monitor
|
65
|
+
class Monitor # :nodoc:
|
66
66
|
def initialize(cycle_length_seconds)
|
67
67
|
@history = History.new(15 * 60 / cycle_length_seconds + 1)
|
68
68
|
@cycle_length_seconds = cycle_length_seconds
|
data/lib/tools/history.rb
CHANGED
@@ -3,83 +3,21 @@ require "spec_helper"
|
|
3
3
|
describe "Heartbeat Events" do
|
4
4
|
include TestHelper
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
def heartbeat!(host_id: nil)
|
10
|
-
host_id ||= null_host_id
|
11
|
-
Postjob::WorkerSession.send(:run_heartbeat_monitor, host_id) do
|
12
|
-
# By returning false we create only a single heartbeat event
|
13
|
-
false
|
6
|
+
describe "::Postjob::Queue.host_heartbeat" do
|
7
|
+
def run!
|
8
|
+
::Postjob::Queue.host_heartbeat(null_host_id, {})
|
14
9
|
end
|
15
|
-
end
|
16
|
-
|
17
|
-
describe "creation" do
|
18
|
-
before { heartbeat! }
|
19
10
|
|
20
11
|
it "creates a heartbeat event" do
|
21
|
-
|
22
|
-
SELECT * FROM postjob.events
|
23
|
-
WHERE name='heartbeat' ORDER BY created_at DESC
|
24
|
-
SQL
|
25
|
-
|
26
|
-
expect(event.worker_session_id).to be_nil
|
27
|
-
expect(event.host_id).to eq(null_host_id)
|
28
|
-
|
29
|
-
expected_keys = %w(
|
30
|
-
cpu_load_1min cpu_load_5min cpu_load_15min
|
31
|
-
disk_available disk_used
|
32
|
-
net_errors_1min net_errors_5min net_errors_15min
|
33
|
-
net_in_1min net_in_5min net_in_15min
|
34
|
-
net_out_1min net_out_5min net_out_15min
|
35
|
-
uptime
|
36
|
-
)
|
37
|
-
|
38
|
-
expect(event.attributes.keys).to include(*expected_keys)
|
39
|
-
end
|
12
|
+
run!
|
40
13
|
|
41
|
-
it "creates a zombie event" do
|
42
14
|
event = Simple::SQL.ask <<~SQL, into: OpenStruct
|
43
15
|
SELECT * FROM postjob.events
|
44
|
-
WHERE name='
|
16
|
+
WHERE name='heartbeat' ORDER BY created_at DESC
|
45
17
|
SQL
|
46
18
|
|
47
19
|
expect(event.worker_session_id).to be_nil
|
48
20
|
expect(event.host_id).to eq(null_host_id)
|
49
|
-
expect(event.attributes.keys).to eq([ "zombie_count" ])
|
50
|
-
expect(event.attributes["zombie_count"]).to be_a(Integer)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
describe "zombie checking" do
|
55
|
-
let!(:job_id) { Postjob.enqueue! "HeartbeatSpecWorkflow" }
|
56
|
-
|
57
|
-
before do
|
58
|
-
# change the job status to processing, and move all timestamps into the past.
|
59
|
-
# This simulates a zombie situation.
|
60
|
-
Simple::SQL.ask "UPDATE postjob.postjobs SET status='processing' WHERE id=$1", job_id
|
61
|
-
Simple::SQL.ask "UPDATE postjob.events SET created_at = (now() at time zone 'utc' - interval '2 hours')"
|
62
|
-
end
|
63
|
-
|
64
|
-
context "when running with the real host_id" do
|
65
|
-
it "detects zombies" do
|
66
|
-
job = load_job(job_id)
|
67
|
-
session = Simple::SQL.ask "SELECT * FROM postjob.worker_sessions WHERE id=$1", job.last_worker_session_id, into: OpenStruct
|
68
|
-
|
69
|
-
heartbeat! host_id: session.host_id
|
70
|
-
|
71
|
-
job = Simple::SQL.ask "SELECT * FROM postjob.postjobs WHERE id=$1", job_id, into: Hash
|
72
|
-
expect(job).to include(status: "err", failed_attempts: 1, error: "Zombie", error_message: "zombie")
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
context "when running with a different host_id" do
|
77
|
-
it "detects zombies" do
|
78
|
-
heartbeat!
|
79
|
-
|
80
|
-
job = Simple::SQL.ask "SELECT * FROM postjob.postjobs WHERE id=$1", job_id, into: Hash
|
81
|
-
expect(job).to include(status: "err", failed_attempts: 1, error: "Zombie", error_message: "zombie")
|
82
|
-
end
|
83
21
|
end
|
84
22
|
end
|
85
23
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module HeartbeatSpecWorkflow
|
4
|
+
Postjob.register_workflow self
|
5
|
+
end
|
6
|
+
|
7
|
+
describe "Heartbeat Events" do
|
8
|
+
include TestHelper
|
9
|
+
|
10
|
+
before do
|
11
|
+
Postjob.enqueue! "HeartbeatSpecWorkflow"
|
12
|
+
|
13
|
+
@host_id = Simple::SQL.ask "SELECT id FROM postjob.hosts WHERE id != $1", null_host_id
|
14
|
+
|
15
|
+
send_heartbeat!
|
16
|
+
|
17
|
+
Simple::SQL.ask "UPDATE postjob.postjobs SET status='processing'"
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:host_id) { @host_id || raise("host_id must be set") }
|
21
|
+
|
22
|
+
def send_heartbeat!
|
23
|
+
::Postjob::Queue.host_heartbeat(host_id, {})
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "::Postjob::Queue.host_heartbeat" do
|
27
|
+
context "zombies in the database" do
|
28
|
+
before do
|
29
|
+
Simple::SQL.ask "UPDATE postjob.events SET created_at = (now() at time zone 'utc' - interval '2 days')"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "does creates a zombie events" do
|
33
|
+
send_heartbeat!
|
34
|
+
|
35
|
+
event = Simple::SQL.ask <<~SQL, into: Hash
|
36
|
+
SELECT * FROM postjob.events
|
37
|
+
WHERE name='zombie' ORDER BY created_at DESC
|
38
|
+
SQL
|
39
|
+
|
40
|
+
expect(event).to include(
|
41
|
+
attributes: { "zombie_count" => 1 },
|
42
|
+
name: "zombie",
|
43
|
+
postjob_id: nil
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "no zombies in the database, 2" do
|
50
|
+
it "does creates a zombie events" do
|
51
|
+
send_heartbeat!
|
52
|
+
|
53
|
+
event = Simple::SQL.ask <<~SQL, into: Hash
|
54
|
+
SELECT * FROM postjob.events
|
55
|
+
WHERE name='zombie' ORDER BY created_at DESC
|
56
|
+
SQL
|
57
|
+
|
58
|
+
expect(event).to be_nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe "Postjob::WorkerSession.start!" do
|
4
|
-
let(:store_path) { ".postjob.host_id" }
|
4
|
+
let(:store_path) { ".postjob.test.host_id" }
|
5
5
|
|
6
6
|
def session_count
|
7
7
|
Simple::SQL.ask "SELECT count(*) from postjob.worker_sessions"
|
@@ -15,27 +15,4 @@ describe "Postjob::WorkerSession.start!" do
|
|
15
15
|
expect(session.id).to match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i)
|
16
16
|
end.to change { session_count }.by(1)
|
17
17
|
end
|
18
|
-
|
19
|
-
it "stores and reuses the host_id" do
|
20
|
-
FileUtils.rm_rf store_path
|
21
|
-
|
22
|
-
session = Postjob::WorkerSession.start!(workflows_with_versions)
|
23
|
-
expect(File.read(store_path)).to match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i)
|
24
|
-
|
25
|
-
session2 = Postjob::WorkerSession.start!(workflows_with_versions)
|
26
|
-
expect(session2.host_id).to eq(session.host_id)
|
27
|
-
end
|
28
|
-
|
29
|
-
context "when passing in an invalid host id" do
|
30
|
-
it "raises an argument error" do
|
31
|
-
invalid_uuid = "foo"
|
32
|
-
File.open store_path, "w" do |io|
|
33
|
-
io.write invalid_uuid
|
34
|
-
end
|
35
|
-
|
36
|
-
expect do
|
37
|
-
Postjob::WorkerSession.start!(workflows_with_versions)
|
38
|
-
end.to raise_error(ArgumentError)
|
39
|
-
end
|
40
|
-
end
|
41
18
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,18 +1,9 @@
|
|
1
1
|
require "active_record"
|
2
|
-
ActiveRecord::Base.establish_connection(adapter: "postgresql",
|
3
|
-
database: "postjob_test",
|
4
|
-
username: "postjob",
|
5
|
-
password: "postjob")
|
6
2
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
# raise ActiveRecord::Rollback, "clean up"
|
15
|
-
# end
|
16
|
-
# end
|
17
|
-
# end
|
18
|
-
# end
|
3
|
+
lambda do
|
4
|
+
require "yaml"
|
5
|
+
configs = YAML.load_file "config/database.yml"
|
6
|
+
config = configs.fetch("test")
|
7
|
+
|
8
|
+
ActiveRecord::Base.establish_connection(config)
|
9
|
+
end.call
|
@@ -5,9 +5,20 @@ else
|
|
5
5
|
end
|
6
6
|
|
7
7
|
RSpec.configure do |config|
|
8
|
+
# This test uses the nil host_id, which is configured during migration.
|
9
|
+
def null_host_id
|
10
|
+
"00000000-0000-0000-0000-000000000000"
|
11
|
+
end
|
12
|
+
|
8
13
|
config.around(:each) do |example|
|
9
14
|
Simple::SQL.ask "DELETE FROM postjob.postjobs"
|
10
15
|
Simple::SQL.ask "DELETE FROM postjob.tokens"
|
16
|
+
Simple::SQL.ask "DELETE FROM postjob.events"
|
17
|
+
Simple::SQL.ask "DELETE FROM postjob.tokens"
|
18
|
+
|
19
|
+
# Simple::SQL.ask "DELETE FROM postjob.hosts"
|
20
|
+
# Simple::SQL.ask "DELETE FROM postjob.worker_sessions"
|
21
|
+
|
11
22
|
example.run
|
12
23
|
end
|
13
24
|
end
|
@@ -1,17 +1 @@
|
|
1
|
-
ENV["DATABASE_URL"] = "postgresql://postjob:postjob@localhost/postjob_test"
|
2
1
|
::Simple::SQL.connect!
|
3
|
-
|
4
|
-
# RSpec.configure do |config|
|
5
|
-
# config.around(:each) do |example|
|
6
|
-
# if example.metadata[:transactions] == false
|
7
|
-
# example.run
|
8
|
-
# else
|
9
|
-
# catch(:rollback) do
|
10
|
-
# ::Simple::SQL.transaction do
|
11
|
-
# example.run
|
12
|
-
# throw :rollback
|
13
|
-
# end
|
14
|
-
# end
|
15
|
-
# end
|
16
|
-
# end
|
17
|
-
# end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: postjob
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- radiospiel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -226,7 +226,9 @@ files:
|
|
226
226
|
- bin/postjob
|
227
227
|
- lib/postjob.rb
|
228
228
|
- lib/postjob/cli.rb
|
229
|
+
- lib/postjob/cli/cron.rb
|
229
230
|
- lib/postjob/cli/db.rb
|
231
|
+
- lib/postjob/cli/enqueue.rb
|
230
232
|
- lib/postjob/cli/events.rb
|
231
233
|
- lib/postjob/cli/heartbeat.rb
|
232
234
|
- lib/postjob/cli/hosts.rb
|
@@ -236,6 +238,7 @@ files:
|
|
236
238
|
- lib/postjob/cli/sessions.rb
|
237
239
|
- lib/postjob/cli/version.rb
|
238
240
|
- lib/postjob/error.rb
|
241
|
+
- lib/postjob/host.rb
|
239
242
|
- lib/postjob/job.rb
|
240
243
|
- lib/postjob/migrations.rb
|
241
244
|
- lib/postjob/migrations/002_statuses.rb
|
@@ -247,19 +250,21 @@ files:
|
|
247
250
|
- lib/postjob/migrations/006_enqueue.sql
|
248
251
|
- lib/postjob/migrations/006a_processing.sql
|
249
252
|
- lib/postjob/migrations/007_job_results.sql
|
250
|
-
- lib/postjob/migrations/008_checkout_runnable.sql
|
251
253
|
- lib/postjob/migrations/008a_childjobs.sql
|
252
254
|
- lib/postjob/migrations/009_tokens.sql
|
253
255
|
- lib/postjob/migrations/010_settings.sql
|
254
256
|
- lib/postjob/migrations/011_null_uuid.sql
|
255
257
|
- lib/postjob/migrations/012_hosts.sql
|
256
258
|
- lib/postjob/migrations/013_worker_sessions.sql
|
259
|
+
- lib/postjob/migrations/013a_checkout_runnable.sql
|
257
260
|
- lib/postjob/migrations/014_postjob_session_id.sql
|
258
261
|
- lib/postjob/migrations/015_events.sql
|
259
262
|
- lib/postjob/migrations/016_sessions_functions.sql
|
260
263
|
- lib/postjob/migrations/017_zombie_check.sql
|
261
264
|
- lib/postjob/migrations/018_heartbeat.sql
|
262
265
|
- lib/postjob/migrations/019_heartbeat_indices.sql
|
266
|
+
- lib/postjob/migrations/021_cron_jobs.sql
|
267
|
+
- lib/postjob/migrations/023_sticky_jobs.sql
|
263
268
|
- lib/postjob/queue.rb
|
264
269
|
- lib/postjob/queue/associations.rb
|
265
270
|
- lib/postjob/queue/encoder.rb
|
@@ -273,12 +278,12 @@ files:
|
|
273
278
|
- lib/postjob/runner.rb
|
274
279
|
- lib/postjob/worker_session.rb
|
275
280
|
- lib/postjob/workflow.rb
|
276
|
-
- lib/tools/atomic_store.rb
|
277
281
|
- lib/tools/heartbeat.rb
|
278
282
|
- lib/tools/history.rb
|
279
283
|
- spec/postjob/enqueue_spec.rb
|
280
284
|
- spec/postjob/events/heartbeat_event_spec.rb
|
281
285
|
- spec/postjob/events/job_event_spec.rb
|
286
|
+
- spec/postjob/events/zombie_event_spec.rb
|
282
287
|
- spec/postjob/full_workflow_spec.rb
|
283
288
|
- spec/postjob/job_control/error_status_spec.rb
|
284
289
|
- spec/postjob/job_control/manual_spec.rb
|
@@ -317,7 +322,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
317
322
|
version: '0'
|
318
323
|
requirements: []
|
319
324
|
rubyforge_project:
|
320
|
-
rubygems_version: 2.
|
325
|
+
rubygems_version: 2.7.7
|
321
326
|
signing_key:
|
322
327
|
specification_version: 4
|
323
328
|
summary: restartable, asynchronous, and distributed processes
|
data/lib/tools/atomic_store.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
module AtomicStore
|
2
|
-
def self.with(path)
|
3
|
-
File.open(path, File::RDWR | File::CREAT, 0644) do |f|
|
4
|
-
f.flock(File::LOCK_EX)
|
5
|
-
value = f.read
|
6
|
-
value = nil if value == ""
|
7
|
-
new_value = yield value
|
8
|
-
expect! new_value => /./
|
9
|
-
next if new_value == value
|
10
|
-
|
11
|
-
f.rewind
|
12
|
-
f.write(new_value)
|
13
|
-
f.flush
|
14
|
-
f.truncate(f.pos)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|