postjob 0.5.5 → 0.5.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|