postjob 0.5.10 → 0.5.11

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: 3a27daa3a8a98739c5b78fe5b74cab7fb9f8d16b
4
- data.tar.gz: 41eab0fe1314594cbeaaa06b364e476855f7839c
3
+ metadata.gz: e26be7454c3a0ddb3d26d67b4e51918e8e16e306
4
+ data.tar.gz: f837746f80bba5cebbdd0fea7c7ad7c26eacbc5b
5
5
  SHA512:
6
- metadata.gz: f89717293ad0920aef170e08a9fbca783e95d509c47153c2e217f9d13f445eb49725b84d349aa1e868858f4a53584f1247e3b0934ceec88ec63ff1e0e37c5f22
7
- data.tar.gz: c600c26793d24e26f51626b0de1e7c741fe0cb11db3f85562f6308ae2184738cd82bdef7d9b8a0bdcb9841987f1b1186c37fddac89a7cc343de0adf5239f1688
6
+ metadata.gz: 361995efdeda5d1ca51de93c0807e37737581c32f53c25f20dc45c50c65dc008260abccc0d421776d59186997071fd2aa14cc23828f95145de6536bcf7859589
7
+ data.tar.gz: f374453e87325c9ddb05d4b1cad18f20d26b3a6c64a596de23ab471bc6bbc57017b20df5c589944e1cc90994ad717e4d1e57b7fa8ec6ab953ef48e6ec0a33adc
data/lib/postjob.rb CHANGED
@@ -88,6 +88,7 @@ module Postjob
88
88
  sticky = spec.options.sticky if sticky.nil?
89
89
  cron_interval = spec.options.cron_interval if cron_interval.nil?
90
90
  queue = spec.options.queue if queue.nil?
91
+ greedy = spec.options.greedy
91
92
  end
92
93
 
93
94
  if cron_interval && cron_interval < 300
@@ -111,7 +112,8 @@ module Postjob
111
112
  tags: tags,
112
113
  version: version,
113
114
  cron_interval: cron_interval,
114
- sticky: sticky
115
+ sticky: sticky,
116
+ greedy: greedy
115
117
 
116
118
  logger.info "Generated process #{job}"
117
119
  job.id
@@ -272,23 +274,30 @@ module Postjob
272
274
  else raise ArgumentError, "Invalid status #{status.inspect}"
273
275
  end
274
276
 
275
- if (status == :ok || status == :failed) && job.workflow_method == "run"
276
- Simple::SQL.transaction do
277
- job_id = enqueue! "#{job.workflow}.cleanup", *job.args, queue: job.queue,
278
- parent_id: nil,
279
- max_attempts: nil,
280
- timeout: nil,
281
- version: version,
282
- tags: job.tags,
283
- cron_interval: nil,
284
- sticky: job.is_sticky
285
-
286
- if job.is_sticky
287
- Simple::SQL.ask "UPDATE postjob.postjobs SET sticky_host_id=$1 WHERE id=$2", job.sticky_host_id, job_id
288
- end
289
- end
290
- end
277
+ enqueue_cleanup(job) if (status == :ok || status == :failed) && job.workflow_method == "run"
291
278
 
292
279
  shutdown
293
280
  end
281
+
282
+ def enqueue_cleanup(job)
283
+ spec = Postjob::Registry.lookup!(name: job.workflow, version: job.workflow_version)
284
+ return unless spec.supports_cleanup?
285
+
286
+ Postjob.logger.info "Enqueuing cleanup job #{spec.name}.cleanup(#{job.args.map(&:inspect).join(", ")})"
287
+
288
+ Simple::SQL.transaction do
289
+ job_id = enqueue! "#{job.workflow}.cleanup", *job.args, queue: job.queue,
290
+ parent_id: nil,
291
+ max_attempts: nil,
292
+ timeout: nil,
293
+ version: job.workflow_version,
294
+ tags: job.tags,
295
+ cron_interval: nil,
296
+ sticky: job.is_sticky
297
+
298
+ if job.is_sticky
299
+ Simple::SQL.ask "UPDATE postjob.postjobs SET sticky_host_id=$1 WHERE id=$2", job.sticky_host_id, job_id
300
+ end
301
+ end
302
+ end
294
303
  end
@@ -6,9 +6,13 @@ module Postjob::CLI
6
6
  #
7
7
  # Note that the workflow will receive the arguments as strings and must be
8
8
  # prepared to handle these.
9
- def enqueue(workflow, *args, queue: nil, tags: nil)
9
+ def enqueue(workflow, *args, queue: nil, tags: nil, count: "1")
10
+ count = Integer(count)
11
+
10
12
  connect_to_database!
11
13
 
12
- Postjob.enqueue! workflow, *args, queue: queue, tags: parse_tags(tags)
14
+ count.times do
15
+ Postjob.enqueue! workflow, *args, queue: queue, tags: parse_tags(tags)
16
+ end
13
17
  end
14
18
  end
@@ -2,11 +2,12 @@
2
2
  # rubocop:disable Metrics/MethodLength
3
3
  # rubocop:disable Metrics/ModuleLength
4
4
  # rubocop:disable Metrics/PerceivedComplexity
5
+ # rubocop:disable Metrics/ParameterLists
5
6
 
6
7
  module Postjob::CLI
7
8
  private
8
9
 
9
- def ps_query(tags:, limit:, queue:)
10
+ def ps_query(tags:, limit:, queue:, only_root: false)
10
11
  limit = Integer(limit)
11
12
 
12
13
  sql = <<-SQL
@@ -31,6 +32,7 @@ module Postjob::CLI
31
32
  WHEN is_sticky THEN COALESCE(substring(sticky_host_id::varchar for 6) || '...', 'yes')
32
33
  ELSE 'no'
33
34
  END AS sticky,
35
+ is_greedy AS greedy,
34
36
  next_run_at,
35
37
  to_char(EXTRACT(EPOCH FROM (next_run_at - now() at time zone 'utc')), '999999999.99') AS next_run_in,
36
38
  to_char(EXTRACT(EPOCH FROM (now() at time zone 'utc' - postjobs.created_at)), '999999999.99') AS age,
@@ -42,6 +44,7 @@ module Postjob::CLI
42
44
  scope = Simple::SQL::Scope.new(sql)
43
45
  scope = scope.where("tags @> ?", Postjob::Queue::Encoder.encode(parse_tags(tags))) if tags
44
46
  scope = scope.where(queue: queue) if queue
47
+ scope = scope.where("id = root_id") if only_root
45
48
 
46
49
  scope
47
50
  .paginate(per: limit, page: 1)
@@ -61,7 +64,7 @@ module Postjob::CLI
61
64
  #
62
65
  # For a listing of all jobs in the system use ps:full, see 'postjob help ps:full'
63
66
  # for details.
64
- def ps(*ids, limit: "100", tags: nil, queue: nil)
67
+ def ps(*ids, limit: "100", tags: nil, queue: nil, only_root: nil)
65
68
  expect! limit => /\A\d+\z/
66
69
  limit = Integer(limit)
67
70
  queue = queue.split(",") if queue
@@ -76,7 +79,7 @@ module Postjob::CLI
76
79
  return
77
80
  end
78
81
 
79
- query = ps_query(tags: tags, limit: limit, queue: queue)
82
+ query = ps_query(tags: tags, limit: limit, queue: queue, only_root: only_root)
80
83
  query = query.where("root_id=id OR status NOT IN ('sleep', 'ok') OR failed_attempts > 0")
81
84
 
82
85
  print_results query: query
@@ -98,13 +101,13 @@ module Postjob::CLI
98
101
  end
99
102
 
100
103
  # Show up-to-date information once per second
101
- def ps_top(*ids, limit: "100", tags: nil, full: false, queue: nil)
104
+ def ps_top(*ids, limit: "100", tags: nil, full: false, queue: nil, only_root: false)
102
105
  loop do
103
106
  system "clear"
104
107
  if full
105
108
  ps_full(*ids, limit: limit, tags: tags, queue: queue)
106
109
  else
107
- ps(*ids, limit: limit, tags: tags, queue: queue)
110
+ ps(*ids, limit: limit, tags: tags, queue: queue, only_root: only_root)
108
111
  end
109
112
  sleep 1
110
113
  end
@@ -14,10 +14,12 @@ module Postjob::CLI
14
14
  # - queue run only the specified queue.
15
15
  # - quiet don't show progress.
16
16
  #
17
- def run(count: nil, queue: nil, quiet: false)
17
+ def run(count: nil, queue: nil, quiet: false, fast: false)
18
18
  count = Integer(count) if count
19
19
  queue = queue.split(",") if queue
20
20
 
21
+ Postjob.fast_mode = (fast ? true : false)
22
+
21
23
  connect_to_database!
22
24
 
23
25
  logger.success "Starting runner with pid #{$$}"
@@ -63,6 +63,16 @@ CREATE TABLE IF NOT EXISTS {SCHEMA_NAME}.postjobs (
63
63
  -- processing_max_duration float -- maximum expected duration of processing. Afterwards the
64
64
  -- processing is considered failed for unknown reasons, and
65
65
  -- potentially restarted.
66
+
67
+ -- process information ------------------------------------------------------------------------
68
+ --
69
+ -- Initially these columns didn't exist, and have been created via another migration.
70
+
71
+ -- last_worker_session_id uuid NOT NULL, -- session_id of last worker that touched this job
72
+ -- cron_interval integer, -- for cron jobs: cron_interval in seconds
73
+ -- is_sticky boolean DEFAULT false NOT NULL, -- when set this job is supposed to be sticky
74
+ -- sticky_host_id uuid -- once a sticky job starts running the job's host id
75
+ -- is_greedy boolean DEFAULT false NOT NULL -- is this a greedy job? (i.e. sticky, and do not allow any other job in this worker.)
66
76
  );
67
77
 
68
78
  -- [TODO] check indices
@@ -23,6 +23,20 @@ DROP FUNCTION IF EXISTS {SCHEMA_NAME}.enqueue(
23
23
  timeout DOUBLE PRECISION,
24
24
  p_cron_interval integer);
25
25
 
26
+ DROP FUNCTION IF EXISTS {SCHEMA_NAME}.enqueue(
27
+ p_worker_session_id UUID,
28
+ queue VARCHAR,
29
+ workflow VARCHAR,
30
+ workflow_method VARCHAR,
31
+ workflow_version VARCHAR,
32
+ args JSONB,
33
+ parent_id BIGINT,
34
+ tags JSONB,
35
+ max_attempts INTEGER,
36
+ timeout DOUBLE PRECISION,
37
+ p_cron_interval INTEGER,
38
+ p_is_sticky BOOLEAN);
39
+
26
40
  CREATE OR REPLACE FUNCTION {SCHEMA_NAME}.enqueue(
27
41
  p_worker_session_id UUID,
28
42
  queue VARCHAR,
@@ -35,7 +49,8 @@ CREATE OR REPLACE FUNCTION {SCHEMA_NAME}.enqueue(
35
49
  max_attempts INTEGER,
36
50
  timeout DOUBLE PRECISION,
37
51
  p_cron_interval INTEGER,
38
- p_is_sticky BOOLEAN)
52
+ p_is_sticky BOOLEAN,
53
+ p_is_greedy BOOLEAN)
39
54
  RETURNS SETOF {SCHEMA_NAME}.postjobs
40
55
  AS $$
41
56
  DECLARE
@@ -62,7 +77,8 @@ AS $$
62
77
  workflow_version := COALESCE(workflow_version, '');
63
78
  queue := COALESCE(queue, 'q');
64
79
  max_attempts := COALESCE(max_attempts, 5);
65
- p_is_sticky := COALESCE(p_is_sticky, FALSE);
80
+ p_is_greedy := COALESCE(p_is_greedy, FALSE);
81
+ p_is_sticky := p_is_greedy OR COALESCE(p_is_sticky, FALSE);
66
82
 
67
83
  -- create postjobs entry ------------------------------------------
68
84
  INSERT INTO {SCHEMA_NAME}.postjobs (
@@ -71,7 +87,8 @@ AS $$
71
87
  parent_id, tags, max_attempts,
72
88
  timing_out_at,
73
89
  cron_interval,
74
- is_sticky
90
+ is_sticky,
91
+ is_greedy
75
92
  )
76
93
  VALUES(
77
94
  p_worker_session_id,
@@ -79,7 +96,8 @@ AS $$
79
96
  parent_id, tags, max_attempts,
80
97
  (now() at time zone 'utc') + timeout * interval '1 second',
81
98
  p_cron_interval,
82
- p_is_sticky
99
+ p_is_sticky,
100
+ p_is_greedy
83
101
  ) RETURNING {SCHEMA_NAME}.postjobs.id INTO job_id;
84
102
 
85
103
  -- fill in root_id and full_id ------------------------------------
@@ -72,10 +72,11 @@ BEGIN
72
72
  v_args, -- args JSONB,
73
73
  v_parent_id, -- parent_id BIGINT,
74
74
  parent.tags, -- tags JSONB,
75
- v_max_attempts, -- max_attempts INTEGER,
75
+ COALESCE(v_max_attempts, parent.max_attempts), -- max_attempts INTEGER,
76
76
  v_timeout, -- timeout
77
77
  NULL, -- cron_interval,
78
- parent.is_sticky -- is_sticky?
78
+ parent.is_sticky, -- is_sticky?,
79
+ parent.is_greedy -- is_greedy?,
79
80
  );
80
81
 
81
82
  UPDATE {SCHEMA_NAME}.postjobs
@@ -6,10 +6,18 @@ AS $$
6
6
  DECLARE
7
7
  p_processable_at timestamp;
8
8
  session {SCHEMA_NAME}.worker_sessions;
9
+ p_current_greedy_job {SCHEMA_NAME}.postjobs;
9
10
  BEGIN
10
11
  SELECT * INTO session
11
12
  FROM {SCHEMA_NAME}.worker_sessions WHERE id=p_worker_session_id;
12
13
 
14
+ SELECT * INTO p_current_greedy_job
15
+ FROM {SCHEMA_NAME}.postjobs WHERE
16
+ status NOT IN ('ok', 'failed') AND
17
+ id=root_id AND
18
+ is_greedy
19
+ LIMIT 1;
20
+
13
21
  SELECT MIN(processable_at) INTO p_processable_at FROM (
14
22
  SELECT MIN(timing_out_at) AS processable_at
15
23
  FROM {SCHEMA_NAME}.postjobs
@@ -20,7 +28,12 @@ BEGIN
20
28
  WHERE status IN ('ready', 'err')
21
29
  AND (p_queue IS NULL OR queue = ANY (p_queue))
22
30
  AND (workflow || workflow_version) = ANY (session.workflows)
23
- AND COALESCE(sticky_host_id, {SCHEMA_NAME}._null_uuid()) IN (session.host_id, {SCHEMA_NAME}._null_uuid())
31
+ AND COALESCE(sticky_host_id, {SCHEMA_NAME}._null_uuid()) IN (session.host_id, {SCHEMA_NAME}._null_uuid()) -- matches sticky_host_id for started sticky jobs and _null_uuid for
32
+ -- non-started or non-sticky jobs against the host_id and _null_uuid
33
+ AND (
34
+ p_current_greedy_job.id IS NULL OR root_id=p_current_greedy_job.root_id -- if there is a greedy job on this host_id which is not finished yet,
35
+ -- only jobs belonging to this root jobs are allowed.
36
+ )
24
37
  ) sq;
25
38
 
26
39
  RETURN EXTRACT(EPOCH FROM p_processable_at - (now() at time zone 'utc'));
@@ -39,10 +52,28 @@ AS $$
39
52
  DECLARE
40
53
  job {SCHEMA_NAME}.postjobs;
41
54
  session {SCHEMA_NAME}.worker_sessions;
55
+ p_current_greedy_job {SCHEMA_NAME}.postjobs;
42
56
  BEGIN
43
57
  SELECT * INTO session
44
58
  FROM {SCHEMA_NAME}.worker_sessions WHERE id=p_worker_session_id;
45
59
 
60
+ --
61
+ -- We don't want multiple sessions to run this function in parallel. This can lead to a situation
62
+ -- where multiple greedy root jobs could be selected for different workers with identical host ids
63
+ -- at the same time. We therefore lock the function here against parallel usage - and we use the
64
+ -- hosts table for locking. This look will be released automatically with the current transaction,
65
+ -- i.e. typically after the "SELECT * FROM checkout(..)" returns.
66
+ --
67
+ PERFORM * FROM {SCHEMA_NAME}.hosts WHERE id=session.host_id FOR UPDATE;
68
+
69
+ SELECT * INTO p_current_greedy_job
70
+ FROM {SCHEMA_NAME}.postjobs WHERE
71
+ status NOT IN ('ok', 'failed')
72
+ AND id=root_id
73
+ AND sticky_host_id=session.host_id
74
+ AND is_greedy
75
+ LIMIT 1;
76
+
46
77
  LOOP
47
78
  -- try to checkout a job. Each of the conditions here is matching
48
79
  -- one of the CASE .. WHEN clauses below.
@@ -56,12 +87,16 @@ BEGIN
56
87
  OR
57
88
  (
58
89
  s.status IN ('ready', 'err')
90
+ AND (p_queue IS NULL OR queue = ANY (p_queue))
59
91
  AND s.next_run_at <= (now() at time zone 'utc')
60
92
  AND (s.workflow || s.workflow_version) = ANY (session.workflows)
61
93
  AND COALESCE(s.sticky_host_id, {SCHEMA_NAME}._null_uuid()) IN (session.host_id, {SCHEMA_NAME}._null_uuid())
62
- AND (p_queue IS NULL OR queue = ANY (p_queue))
94
+ AND (
95
+ p_current_greedy_job.id IS NULL OR s.root_id=p_current_greedy_job.root_id -- if there is a greedy job on this host_id which is not finished yet,
96
+ -- only jobs belonging to this root jobs are allowed.
97
+ )
63
98
  )
64
- ORDER BY (LEAST(CASE WHEN s.sticky_host_id IS NOT NULL THEN s.next_run_at - interval '180 seconds' ELSE s.next_run_at END, s.timing_out_at))
99
+ ORDER BY (LEAST(s.next_run_at, s.timing_out_at))
65
100
  FOR UPDATE SKIP LOCKED
66
101
  LIMIT 1;
67
102
 
@@ -14,3 +14,11 @@ DO $$
14
14
  WHEN duplicate_column THEN RAISE DEBUG 'column {SCHEMA_NAME}.postjobs.sticky_host_id already exists';
15
15
  END;
16
16
  $$;
17
+
18
+ DO $$
19
+ BEGIN
20
+ ALTER TABLE {SCHEMA_NAME}.postjobs ADD COLUMN is_greedy BOOLEAN NOT NULL DEFAULT FALSE;
21
+ EXCEPTION
22
+ WHEN duplicate_column THEN RAISE DEBUG 'column {SCHEMA_NAME}.postjobs.is_greedy already exists';
23
+ END;
24
+ $$;
data/lib/postjob/queue.rb CHANGED
@@ -43,17 +43,23 @@ module Postjob::Queue
43
43
  tags: [Hash, nil],
44
44
  timeout: [Numeric, nil],
45
45
  max_attempts: [Integer, nil],
46
- sticky: [true, false, nil]
46
+ sticky: [true, false, nil],
47
+ greedy: [true, false, nil]
47
48
  }
48
49
 
49
50
  workflow, workflow_method = parse_workflow(workflow)
50
51
 
52
+ if options[:greedy] && !options[:sticky]
53
+ raise ArgumentError, "#{workflow}: A greedy job must also be sticky" unless options[:sticky].nil?
54
+ options[:sticky] = true if options[:greedy]
55
+ end
56
+
51
57
  # The use of a `SELECT * FROM function()` here is due to
52
58
  #
53
59
  # a) a limitation in Simple::SQL which would not be able to unpack a
54
60
  # "SELECT function()" usefully when the return value is a record;
55
61
  # b) and/or my inability to write better SQL functions;
56
- SQL.ask "SELECT * FROM #{SCHEMA_NAME}.enqueue($1::uuid, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)",
62
+ SQL.ask "SELECT * FROM #{SCHEMA_NAME}.enqueue($1::uuid, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)",
57
63
  worker_session_id,
58
64
  options[:queue],
59
65
  workflow,
@@ -66,6 +72,7 @@ module Postjob::Queue
66
72
  options[:timeout],
67
73
  options[:cron_interval],
68
74
  options[:sticky],
75
+ options[:greedy],
69
76
  into: Job
70
77
  end
71
78
 
@@ -162,7 +169,6 @@ module Postjob::Queue
162
169
  expect! queue => [ nil, Array, String ]
163
170
 
164
171
  queue = Array(queue) if queue
165
-
166
172
  SQL.ask "SELECT * FROM #{SCHEMA_NAME}.checkout($1::uuid, $2::boolean, $3)",
167
173
  worker_session_id, Postjob.fast_mode, queue, into: Job
168
174
  end
@@ -41,6 +41,7 @@ class Postjob::Registry
41
41
  max_attempts: 5,
42
42
  timeout: 15 * 60,
43
43
  sticky: false,
44
+ greedy: false,
44
45
  cron_interval: nil,
45
46
  queue: "ruby"
46
47
  }
@@ -49,6 +50,7 @@ class Postjob::Registry
49
50
  attr_reader :max_attempts
50
51
  attr_reader :timeout
51
52
  attr_reader :sticky
53
+ attr_reader :greedy
52
54
  attr_reader :cron_interval
53
55
  attr_reader :queue
54
56
 
@@ -64,10 +66,13 @@ class Postjob::Registry
64
66
 
65
67
  options = DEFAULTS.merge(options)
66
68
 
69
+ options[:sticky] ||= options[:greedy]
70
+
67
71
  @version = options[:version]
68
72
  @max_attempts = options[:max_attempts]
69
73
  @timeout = options[:timeout]
70
74
  @sticky = options[:sticky]
75
+ @greedy = options[:greedy]
71
76
  @cron_interval = options[:cron_interval]
72
77
  @queue = options[:queue]
73
78
  end
@@ -78,6 +83,7 @@ class Postjob::Registry
78
83
  r[:max_attempts] = @max_attempts
79
84
  r[:timeout] = @timeout
80
85
  r[:sticky] = @sticky
86
+ r[:greedy] = @greedy
81
87
  r[:cron_interval] = @cron_interval
82
88
  r[:queue] = @queue
83
89
 
@@ -109,6 +115,22 @@ class Postjob::Registry
109
115
  @workflow = workflow
110
116
  @options = Options.new(options)
111
117
  end
118
+
119
+ def supports_cleanup?
120
+ return false unless lookup_workflow_method(:run)
121
+ return false unless lookup_workflow_method(:cleanup)
122
+
123
+ true
124
+ end
125
+
126
+ private
127
+
128
+ def lookup_workflow_method(name)
129
+ return unless workflow.is_a?(Module)
130
+ workflow.method(name)
131
+ rescue NameError
132
+ nil
133
+ end
112
134
  end
113
135
 
114
136
  # looks up a specific version of a specific workflow. Returns a WorkflowSpec
@@ -132,6 +154,10 @@ class Postjob::Registry
132
154
  end
133
155
 
134
156
  def register(workflow, options)
157
+ if options[:greedy] && options[:sticky] == false
158
+ raise ArgumentError, "#{workflow}: a greedy job must also be sticky"
159
+ end
160
+
135
161
  spec = WorkflowSpec.new(workflow, options)
136
162
 
137
163
  @workflows_with_versions << spec.name << "#{spec.name}#{spec.options.version}"
@@ -2,6 +2,7 @@
2
2
  # rubocop:disable Style/BlockDelimiters
3
3
  # rubocop:disable Lint/RescueException
4
4
  # rubocop:disable Metrics/MethodLength
5
+ # rubocop:disable Metrics/AbcSize
5
6
 
6
7
  # Base implementations for Runners
7
8
  #
@@ -155,6 +156,10 @@ module Postjob::Runner
155
156
  return_exception :failed, $!
156
157
  rescue Postjob::Error::Nonrecoverable
157
158
  return_exception :failed, $!
159
+ rescue PG::Error
160
+ Postjob.logger.error "#{$!}, from\n\t#{$!.backtrace[0, 10].join("\n\t")}"
161
+ STDERR.puts "#{$!}, from\n\t#{$!.backtrace[0, 10].join("\n\t")}"
162
+ return_exception :failed, $!
158
163
  rescue Exception
159
164
  return_exception :err, $!
160
165
  end
@@ -23,7 +23,7 @@ describe "Postjob.process_all" do
23
23
  let!(:id) { Postjob.enqueue! "TwoLevelWorkflow" }
24
24
 
25
25
  it "runs the job returning the result" do
26
- expect(Postjob.process_all).to eq(5)
26
+ expect(Postjob.process_all).to eq(3)
27
27
  processed_job = load_job(id)
28
28
  expect(processed_job.status).to eq("ok")
29
29
  expect(processed_job.resolve).to eq("my string")
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.10
4
+ version: 0.5.11
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-15 00:00:00.000000000 Z
11
+ date: 2018-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec