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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 79193eb5de0de5ad5a9de485fd40378c66907c22
4
- data.tar.gz: 252abc25bfdb766849168de4bef806c5938d9983
3
+ metadata.gz: 0be2321073faba782e89878c47c6c6770b97e7ff
4
+ data.tar.gz: c9d3cf35e02a4105587d5888535e4297d4abb9af
5
5
  SHA512:
6
- metadata.gz: 458b190937d133249530d48d6cc16d96f94c8ced9af36d944e1c71144112045849ea04fdd348346b9dd419106eae4a189a3acd1b6c966fea5c543d7474261d8f
7
- data.tar.gz: 6d7e015d27c697b26bd8aa39d045e1efaada633fcd1b2db11a0acdb83c48a69e8e77ab7313bd98e26a1db3412a9107b3f3ca36e4e17a091fae68d0cd2d103579
6
+ metadata.gz: 208afca0daf608d1ada39ad4fac5539e2ad10388d73e469bc4164eee2f49c4615a0e845578dd1aad5db6fe33f0decdef62c0329b198fa4f44f2e9941363eb2e7
7
+ data.tar.gz: 11a854fb585336169a6b218884d8b02503c5e52503efac95609b937dc18dd51703868f93a569f3fb66b557c411215bf9ecf797f5ddd33a4781a750092676855f
@@ -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
- workflow_status AS status,
22
- status,
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
- CASE WHEN processing_started_at IS NOT NULL THEN
29
- format(
30
- '%s/%s',
31
- to_char(EXTRACT(EPOCH FROM (now() at time zone 'utc') - processing_started_at), '999999999.99'),
32
- processing_max_duration
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
@@ -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, fast: false, quiet: false)
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
- def initialize(job)
4
- @job = job
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
- def message
8
- msg = "Failing child job"
9
- msg += " [#{@job.result}]" if @job.result
10
- msg
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 NOTICE 'column {SCHEMA_NAME}.postjobs.processing_client already exists';
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 NOTICE 'column {SCHEMA_NAME}.postjobs.processing_client_identifier already exists';
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 NOTICE 'column {SCHEMA_NAME}.postjobs.processing_started_at already exists';
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 NOTICE 'column {SCHEMA_NAME}.postjobs.processing_max_duration already exists';
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
- INSERT INTO {SCHEMA_NAME}.settings (name, value) VALUES('version', '0.4.0') ON CONFLICT DO NOTHING;
7
- INSERT INTO {SCHEMA_NAME}.settings (name, value) VALUES('client_version', '{CLIENT_VERSION}') ON CONFLICT DO NOTHING;
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}');
@@ -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
- STDERR.puts "[postjob] Running migration in #{file}"
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 ArgumentError, msg
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, workflow => String, args => Array
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
 
@@ -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
- case value
123
- when :pending then [ :pending, nil, nil ]
124
- else [ :ok, value, nil ]
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
- it "cannot encode Symbols on input" do
41
- expect do
42
- run_workflow input: :foo
43
- end.to raise_error(ArgumentError)
44
-
45
- expect do
46
- run_workflow output: :foo
47
- end.to raise_error(ArgumentError)
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.2
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-04 00:00:00.000000000 Z
11
+ date: 2018-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec