postjob 0.4.2 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/postjob/cli/ps.rb +15 -8
- data/lib/postjob/cli/run.rb +1 -3
- data/lib/postjob/error.rb +21 -6
- data/lib/postjob/migrations/003b_processing_columns.sql +4 -4
- data/lib/postjob/migrations/006_enqueue.sql +5 -0
- data/lib/postjob/migrations/010_settings.sql +11 -2
- data/lib/postjob/migrations.rb +2 -1
- data/lib/postjob/queue/encoder.rb +8 -2
- data/lib/postjob/queue.rb +8 -1
- data/lib/postjob/runner.rb +13 -3
- data/lib/postjob.rb +11 -0
- data/spec/postjob/job_control/manual_spec.rb +7 -3
- data/spec/postjob/queue/encoder_spec.rb +21 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0be2321073faba782e89878c47c6c6770b97e7ff
|
4
|
+
data.tar.gz: c9d3cf35e02a4105587d5888535e4297d4abb9af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 208afca0daf608d1ada39ad4fac5539e2ad10388d73e469bc4164eee2f49c4615a0e845578dd1aad5db6fe33f0decdef62c0329b198fa4f44f2e9941363eb2e7
|
7
|
+
data.tar.gz: 11a854fb585336169a6b218884d8b02503c5e52503efac95609b937dc18dd51703868f93a569f3fb66b557c411215bf9ecf797f5ddd33a4781a750092676855f
|
data/lib/postjob/cli/ps.rb
CHANGED
@@ -18,20 +18,27 @@ module Postjob::CLI
|
|
18
18
|
|| workflow_version
|
19
19
|
|| (CASE WHEN workflow_method != 'run' THEN '.' || workflow_method ELSE '' END)
|
20
20
|
|| args AS job,
|
21
|
-
|
22
|
-
|
21
|
+
CASE
|
22
|
+
WHEN (status = 'err') THEN 'err(' || failed_attempts || '/' || max_attempts || ')'
|
23
|
+
ELSE status::varchar
|
24
|
+
END AS status,
|
23
25
|
error,
|
24
26
|
COALESCE((results->0)::varchar, error_message) AS result,
|
25
27
|
next_run_at,
|
26
28
|
next_run_at - (now() at time zone 'utc') AS next_run_in,
|
27
29
|
to_char(EXTRACT(EPOCH FROM (now() at time zone 'utc') - postjobs.created_at), '999999999.99') AS age,
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
|
31
|
+
CASE
|
32
|
+
WHEN processing_started_at IS NOT NULL THEN
|
33
|
+
format(
|
34
|
+
'%s/%s',
|
35
|
+
to_char(EXTRACT(EPOCH FROM (now() at time zone 'utc') - processing_started_at), '999999999.99'),
|
36
|
+
processing_max_duration
|
37
|
+
)
|
38
|
+
WHEN status IN ('failed', 'err', 'ok') THEN
|
39
|
+
format('%s', to_char(EXTRACT(EPOCH FROM (updated_at - created_at)), '999999999.99'))
|
34
40
|
END AS processing,
|
41
|
+
|
35
42
|
COALESCE(processing_client, '') || COALESCE('/' || processing_client_identifier, '') AS worker,
|
36
43
|
tags
|
37
44
|
FROM postjob.postjobs AS postjobs
|
data/lib/postjob/cli/run.rb
CHANGED
@@ -11,12 +11,10 @@ module Postjob::CLI
|
|
11
11
|
# Parameters:
|
12
12
|
#
|
13
13
|
# - count=<count> maximum number of jobs to process. Default: unlimited.
|
14
|
-
# - fast=<count> reduce waiting time after error (for development only!)
|
15
14
|
# - quiet don't show progress.
|
16
15
|
#
|
17
|
-
def run(count: nil,
|
16
|
+
def run(count: nil, quiet: false)
|
18
17
|
count = Integer(count) if count
|
19
|
-
Postjob.fast_mode = fast
|
20
18
|
|
21
19
|
connect_to_database!
|
22
20
|
|
data/lib/postjob/error.rb
CHANGED
@@ -1,16 +1,31 @@
|
|
1
1
|
module Postjob
|
2
2
|
class Error < RuntimeError
|
3
|
-
|
4
|
-
|
3
|
+
attr_reader :message
|
4
|
+
|
5
|
+
def initialize(err)
|
6
|
+
case err
|
7
|
+
when ::Postjob::Job then @message = job_error_msg(err)
|
8
|
+
when nil, false then @message = self.class.name
|
9
|
+
else @message = err.to_s
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
message
|
5
15
|
end
|
6
16
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
17
|
+
private
|
18
|
+
|
19
|
+
def job_error_msg(job)
|
20
|
+
error_msg = "Failing child job"
|
21
|
+
error_msg += " [#{job.result}]" if job.result
|
22
|
+
error_msg
|
11
23
|
end
|
12
24
|
end
|
13
25
|
|
14
26
|
class Error::Nonrecoverable < Error
|
15
27
|
end
|
28
|
+
|
29
|
+
class Error::Encoding < Error::Nonrecoverable
|
30
|
+
end
|
16
31
|
end
|
@@ -2,7 +2,7 @@ DO $$
|
|
2
2
|
BEGIN
|
3
3
|
ALTER TABLE {SCHEMA_NAME}.postjobs ADD COLUMN processing_client varchar;
|
4
4
|
EXCEPTION
|
5
|
-
WHEN duplicate_column THEN RAISE
|
5
|
+
WHEN duplicate_column THEN RAISE DEBUG 'column {SCHEMA_NAME}.postjobs.processing_client already exists';
|
6
6
|
END;
|
7
7
|
$$;
|
8
8
|
|
@@ -10,7 +10,7 @@ DO $$
|
|
10
10
|
BEGIN
|
11
11
|
ALTER TABLE {SCHEMA_NAME}.postjobs ADD COLUMN processing_client_identifier varchar;
|
12
12
|
EXCEPTION
|
13
|
-
WHEN duplicate_column THEN RAISE
|
13
|
+
WHEN duplicate_column THEN RAISE DEBUG 'column {SCHEMA_NAME}.postjobs.processing_client_identifier already exists';
|
14
14
|
END;
|
15
15
|
$$;
|
16
16
|
|
@@ -18,7 +18,7 @@ DO $$
|
|
18
18
|
BEGIN
|
19
19
|
ALTER TABLE {SCHEMA_NAME}.postjobs ADD COLUMN processing_started_at timestamp;
|
20
20
|
EXCEPTION
|
21
|
-
WHEN duplicate_column THEN RAISE
|
21
|
+
WHEN duplicate_column THEN RAISE DEBUG 'column {SCHEMA_NAME}.postjobs.processing_started_at already exists';
|
22
22
|
END;
|
23
23
|
$$;
|
24
24
|
|
@@ -26,6 +26,6 @@ DO $$
|
|
26
26
|
BEGIN
|
27
27
|
ALTER TABLE {SCHEMA_NAME}.postjobs ADD COLUMN processing_max_duration float;
|
28
28
|
EXCEPTION
|
29
|
-
WHEN duplicate_column THEN RAISE
|
29
|
+
WHEN duplicate_column THEN RAISE DEBUG 'column {SCHEMA_NAME}.postjobs.processing_max_duration already exists';
|
30
30
|
END;
|
31
31
|
$$;
|
@@ -14,6 +14,11 @@ AS $$
|
|
14
14
|
job_id BIGINT;
|
15
15
|
BEGIN
|
16
16
|
-- set defaults ---------------------------------------------------
|
17
|
+
IF workflow = '__manual__' AND COALESCE(max_attempts, 1) != 1 THEN
|
18
|
+
RAISE NOTICE 'Adjusting max_attempts of __manual__ job to 1';
|
19
|
+
max_attempts := 1;
|
20
|
+
END IF;
|
21
|
+
|
17
22
|
workflow_version := COALESCE(workflow_version, '');
|
18
23
|
queue := COALESCE(queue, 'q');
|
19
24
|
max_attempts := COALESCE(max_attempts, 5);
|
@@ -3,5 +3,14 @@ CREATE TABLE IF NOT EXISTS {SCHEMA_NAME}.settings (
|
|
3
3
|
value VARCHAR
|
4
4
|
);
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
CREATE OR REPLACE FUNCTION {SCHEMA_NAME}.update_settings(p_name VARCHAR, p_value VARCHAR)
|
7
|
+
RETURNS VOID
|
8
|
+
AS $$
|
9
|
+
BEGIN
|
10
|
+
INSERT INTO {SCHEMA_NAME}.settings (name, value) VALUES(p_name, p_value)
|
11
|
+
ON CONFLICT(name) DO UPDATE SET value = p_value;
|
12
|
+
END;
|
13
|
+
$$ LANGUAGE plpgsql;
|
14
|
+
|
15
|
+
SELECT {SCHEMA_NAME}.update_settings('version', '0.4.2');
|
16
|
+
SELECT {SCHEMA_NAME}.update_settings('client_version', '{CLIENT_VERSION}');
|
data/lib/postjob/migrations.rb
CHANGED
@@ -16,6 +16,7 @@ module Postjob
|
|
16
16
|
expect! SCHEMA_NAME != "public"
|
17
17
|
|
18
18
|
def unmigrate!
|
19
|
+
SQL.exec "SET client_min_messages TO WARNING"
|
19
20
|
SQL.exec "DROP SCHEMA IF EXISTS #{SCHEMA_NAME} CASCADE"
|
20
21
|
end
|
21
22
|
|
@@ -30,7 +31,7 @@ module Postjob
|
|
30
31
|
private
|
31
32
|
|
32
33
|
def run_migration(file)
|
33
|
-
|
34
|
+
Postjob.logger.debug "[postjob] Running migration in #{file}"
|
34
35
|
|
35
36
|
case file
|
36
37
|
when /\.rb$/ then run_migration_ruby(file)
|
@@ -16,11 +16,17 @@ require "json"
|
|
16
16
|
module Postjob::Queue::Encoder
|
17
17
|
extend self
|
18
18
|
|
19
|
+
def check_encodable!(data)
|
20
|
+
encode(data)
|
21
|
+
end
|
22
|
+
|
19
23
|
def encode(data)
|
20
24
|
return nil if data.nil?
|
21
25
|
|
22
26
|
verify_encodable!(data)
|
23
|
-
JSON.generate(data)
|
27
|
+
::JSON.generate(data)
|
28
|
+
rescue ::JSON::JSONError, ::EncodingError
|
29
|
+
raise ::Postjob::Error::Encoding, $!.to_s
|
24
30
|
end
|
25
31
|
|
26
32
|
private
|
@@ -35,7 +41,7 @@ module Postjob::Queue::Encoder
|
|
35
41
|
when Array then obj.each { |entry| verify_encodable!(entry) }
|
36
42
|
else
|
37
43
|
msg = "Unencodable #{obj.class.name} object: #{obj.inspect}"
|
38
|
-
raise
|
44
|
+
raise ::Postjob::Error::Encoding, msg
|
39
45
|
end
|
40
46
|
end
|
41
47
|
end
|
data/lib/postjob/queue.rb
CHANGED
@@ -89,7 +89,14 @@ module Postjob::Queue
|
|
89
89
|
end
|
90
90
|
|
91
91
|
def find_or_create_childjob(parent, workflow, args, timeout:, max_attempts:, queue: nil)
|
92
|
-
expect! parent => Job
|
92
|
+
expect! parent => Job
|
93
|
+
expect! workflow => String
|
94
|
+
expect! args => Array
|
95
|
+
|
96
|
+
if workflow == "__manual__" && max_attempts != 1
|
97
|
+
Postjob.logger.info "Job ##{parent.id} adjusting max_attempts of '__manual__' child job"
|
98
|
+
max_attempts = 1
|
99
|
+
end
|
93
100
|
|
94
101
|
workflow, workflow_method = parse_workflow(workflow)
|
95
102
|
|
data/lib/postjob/runner.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# rubocop:disable Metrics/ModuleLength
|
2
2
|
# rubocop:disable Style/BlockDelimiters
|
3
3
|
# rubocop:disable Lint/RescueException
|
4
|
+
# rubocop:disable Metrics/MethodLength
|
4
5
|
|
5
6
|
module Postjob::Runner
|
6
7
|
extend self
|
@@ -119,13 +120,22 @@ module Postjob::Runner
|
|
119
120
|
workflow.public_send workflow_method, *args
|
120
121
|
}
|
121
122
|
|
122
|
-
|
123
|
-
|
124
|
-
else
|
123
|
+
if value == :pending
|
124
|
+
[ :pending, nil, nil ]
|
125
|
+
else
|
126
|
+
# Check that we can encode the value. If we can't the job returned something invalid
|
127
|
+
# i.e. something we cannot encode as JSON. This will raise a Postjob::Queue::Encoder::Error.
|
128
|
+
#
|
129
|
+
# Usually this points to a non-UTF8 string.
|
130
|
+
# This is a fix for https://github.com/mediapeers/postjob/issues/35
|
131
|
+
Postjob::Queue::Encoder.check_encodable!([value])
|
132
|
+
[ :ok, value, nil ]
|
125
133
|
end
|
126
134
|
rescue ArgumentError, LocalJumpError, NameError, RegexpError, ScriptError, TypeError
|
127
135
|
Postjob.logger.error "#{$!}, from\n\t#{$!.backtrace[0, 10].join("\n\t")}"
|
128
136
|
return_exception :failed, $!
|
137
|
+
rescue Postjob::Error::Nonrecoverable
|
138
|
+
return_exception :failed, $!
|
129
139
|
rescue Exception
|
130
140
|
return_exception :err, $!
|
131
141
|
end
|
data/lib/postjob.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# rubocop:disable Metrics/ParameterLists
|
2
|
+
# rubocop:disable Metrics/MethodLength
|
2
3
|
|
3
4
|
require "expectation"
|
4
5
|
require "simple/sql"
|
@@ -40,6 +41,16 @@ module Postjob
|
|
40
41
|
expect! timeout => [nil, Numeric]
|
41
42
|
expect! tags => [nil, Hash]
|
42
43
|
|
44
|
+
if workflow == "__manual__" && max_attempts != 1
|
45
|
+
if parent_id
|
46
|
+
Postjob.logger.info "Job ##{parent_id} adjusting max_attempts of '__manual__' child job"
|
47
|
+
else
|
48
|
+
Postjob.logger.info "Adjusting max_attempts of '__manual__' root job"
|
49
|
+
end
|
50
|
+
|
51
|
+
max_attempts = 1
|
52
|
+
end
|
53
|
+
|
43
54
|
tags = stringify_hash(tags) if tags
|
44
55
|
job = Queue.enqueue_job workflow, *args, queue: queue,
|
45
56
|
parent_id: parent_id,
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
module ManualWorkflow
|
4
|
-
def self.run
|
5
|
-
job = async :manual, timeout: 10
|
4
|
+
def self.run(max_attempts)
|
5
|
+
job = async :manual, timeout: 10, max_attempts: max_attempts
|
6
6
|
_token = workflow_token job
|
7
7
|
manual_result = await job
|
8
8
|
"manual-result:#{manual_result}"
|
@@ -12,7 +12,7 @@ module ManualWorkflow
|
|
12
12
|
end
|
13
13
|
|
14
14
|
describe "manual processing" do
|
15
|
-
let!(:id) { Postjob.enqueue! "ManualWorkflow" }
|
15
|
+
let!(:id) { Postjob.enqueue! "ManualWorkflow", 3 }
|
16
16
|
|
17
17
|
include TestHelper
|
18
18
|
|
@@ -24,6 +24,10 @@ describe "manual processing" do
|
|
24
24
|
TestHelper.load_job "SELECT * FROM postjobs WHERE parent_id=$1", id
|
25
25
|
end
|
26
26
|
|
27
|
+
it "sets max_attempts to 1" do
|
28
|
+
expect(load_child_job[:max_attempts]).to eq(1)
|
29
|
+
end
|
30
|
+
|
27
31
|
it "creates a UUID token" do
|
28
32
|
token = load_token(load_child_job)
|
29
33
|
expect! token => /[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[a-fA-F0-9]{4}-[A-F0-9]{12}/i
|
@@ -37,14 +37,27 @@ describe "Postjob::Queue::Encoder" do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
describe "invalid input" do
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
40
|
+
def self.check_value(value)
|
41
|
+
it "cannot encode input" do
|
42
|
+
expect do
|
43
|
+
run_workflow input: value
|
44
|
+
end.to raise_error(::Postjob::Error::Encoding)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "cannot encode output" do
|
48
|
+
expect do
|
49
|
+
run_workflow output: value
|
50
|
+
end.to raise_error(::Postjob::Error::Encoding)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when encoding symbols" do
|
55
|
+
check_value :foo
|
56
|
+
end
|
57
|
+
|
58
|
+
context "when encoding invalid utf8 strings" do
|
59
|
+
check_value 255.chr.force_encoding("utf-8")
|
60
|
+
check_value 255.chr
|
48
61
|
end
|
49
62
|
end
|
50
63
|
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.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- radiospiel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-06-
|
11
|
+
date: 2018-06-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|