startback-jobs 0.15.4 → 0.15.5

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
  SHA256:
3
- metadata.gz: b9f52906536b68aca921b237f543d8c318dccb9fbb8f8529452a1bc110de69f4
4
- data.tar.gz: ae92e6c795a93c467b9b3ecf4372294aacc40fd5437e7d9e0ab39531f4c632b4
3
+ metadata.gz: dea8bb6951ccc73ca5eafdfea151129905ab26dfea75d1ea9dfc824204a6131f
4
+ data.tar.gz: 8a2e8ae265595a674bd8c2afcf43619df1bba338a0cde5900fe333ecee874013
5
5
  SHA512:
6
- metadata.gz: 5e17019a71d938b84e1a81e21c073cf238df721d05443a02304e1ed70f2030a237cfbeca009f6083b73161546cce80857f94a7fd4142db5f8b3e67107a6f7b7c
7
- data.tar.gz: 7f8b2d724578961575ed3ab73bb53cfd47e08c211dfa80314ae408e316aea583967d88c8b6e0083eab60a768b793b32daa78e856b6a4e71d605e9e94c741ae6f
6
+ metadata.gz: 627a7f6a0ddb28fe9a08120fbd2cf8240a29811fc8ae35151d65501a3f563c82fb265c18ad0f22d514ad5f8c6e2cd6ffb5c51c3ac6d212271ab3cdc4d725a126
7
+ data.tar.gz: 33362ef7e67b2f176f489e40aeb6a0b62ef90b231fb5bf079cef4ab243e55e04ebf72916dc2b7ba5801791a048b5c56382661ea229fa103abd6d6a2893d5007b
@@ -18,6 +18,14 @@ module Startback
18
18
  !ready?
19
19
  end
20
20
 
21
+ def failed?
22
+ !!self[:hasFailed]
23
+ end
24
+
25
+ def succeeded?
26
+ !failed?
27
+ end
28
+
21
29
  def expired?
22
30
  self.expiredAt && self.expiredAt < Time.now
23
31
  end
@@ -15,6 +15,7 @@ module Startback
15
15
  strategy: 'NotReady',
16
16
  strategyOptions: {},
17
17
  expiresAt: nil,
18
+ hasFailed: false,
18
19
  refreshFreq: nil,
19
20
  refreshedAt: nil,
20
21
  consumeMax: nil,
@@ -14,12 +14,16 @@ module Startback
14
14
  job_class = ::Kernel.const_get(@job.op_class)
15
15
  job_input = @job.op_input
16
16
 
17
- op_result = with_context(job_context) do
18
- run job_class.new(job_input)
17
+ has_failed, op_result = with_context(job_context) do
18
+ op_result = run job_class.new(job_input)
19
+ [false, op_result]
20
+ rescue => err
21
+ [true, error_to_result(err) ]
19
22
  end
20
23
 
21
24
  services.update_job!(input, {
22
25
  opResult: op_result,
26
+ hasFailed: has_failed,
23
27
  isReady: true,
24
28
  strategy: 'Embedded',
25
29
  })
@@ -27,6 +31,14 @@ module Startback
27
31
  op_result
28
32
  end
29
33
 
34
+ def error_to_result(err)
35
+ {
36
+ errClass: err.class.name.to_s,
37
+ message: err.message,
38
+ backtrace: err.backtrace
39
+ }
40
+ end
41
+
30
42
  emits(Event::JobRan) do
31
43
  { id: @job.id }
32
44
  end
@@ -4,12 +4,25 @@ module Startback
4
4
  class JobResult
5
5
  class Embedded < JobResult
6
6
 
7
+ # Non HTTP-standard special success code to
8
+ # indicate a job failure...
9
+ FAILURE_STATUS_CODE = 272
10
+
7
11
  def api_serve(api)
8
- [
9
- 200,
10
- {"Content-Type" => "application/json"},
11
- [job.opResult.to_json]
12
- ]
12
+ if job.failed?
13
+ payload = job.opResult.delete_if{|k| k == :backtrace }
14
+ [
15
+ FAILURE_STATUS_CODE,
16
+ {"Content-Type" => "application/json"},
17
+ [payload.to_json]
18
+ ]
19
+ else
20
+ [
21
+ 200,
22
+ {"Content-Type" => "application/json"},
23
+ [job.opResult.to_json]
24
+ ]
25
+ end
13
26
  end
14
27
 
15
28
  end # class Embedded
@@ -11,10 +11,10 @@ module Startback
11
11
  attr_reader :job
12
12
 
13
13
  def self.for(job)
14
- unless job.is_ready?
15
- JobResult::NotReady.new(job)
16
- else
14
+ if job.is_ready?
17
15
  JobResult.const_get(job.strategy).new(job)
16
+ else
17
+ JobResult::NotReady.new(job)
18
18
  end
19
19
  end
20
20
 
@@ -11,21 +11,22 @@ Job.Ref = {
11
11
  Job.Strategy = String(s | %w{Embedded NotReady Redirect}.include? s )
12
12
 
13
13
  Job.Full = {
14
- id : String
15
- opClass : ClassName
16
- opInput : DumpableHash
17
- opContext : DumpableHash
18
- opResult : .
19
- isReady : Boolean
20
- strategy : Job.Strategy
21
- strategyOptions : DumpableHash
22
- expiresAt : DateTime|Time|Nil
23
- refreshFreq : String|Nil
24
- refreshedAt : DateTime|Time|Nil
25
- consumeMax : Integer|Nil
26
- consumeCount : Integer|Nil
27
- createdAt : DateTime|Time|Nil
28
- createdBy : String|Nil
14
+ id : String
15
+ opClass : ClassName
16
+ opInput : DumpableHash
17
+ opContext : DumpableHash
18
+ opResult : .
19
+ isReady : Boolean
20
+ hasFailed :? Boolean
21
+ strategy : Job.Strategy
22
+ strategyOptions : DumpableHash
23
+ expiresAt : DateTime|Time|Nil
24
+ refreshFreq : String|Nil
25
+ refreshedAt : DateTime|Time|Nil
26
+ consumeMax : Integer|Nil
27
+ consumeCount : Integer|Nil
28
+ createdAt : DateTime|Time|Nil
29
+ createdBy : String|Nil
29
30
  }
30
31
 
31
32
  Job.CreationRequest = {
data/spec/spec_helper.rb CHANGED
@@ -15,10 +15,11 @@ RSpec.configure do |c|
15
15
  id: 'abcdef',
16
16
  isReady: false,
17
17
  opClass: 'CowSay',
18
- opInput: { 'message' => 'Hello !!' },
18
+ opInput: { 'message' => 'Hello !!', 'crash' => false },
19
19
  opContext: {},
20
20
  opResult: nil,
21
21
  strategy: 'NotReady',
22
+ hasFailed: false,
22
23
  strategyOptions: {},
23
24
  expiresAt: nil,
24
25
  refreshFreq: nil,
@@ -37,6 +38,7 @@ class CowSay < Startback::Operation
37
38
  end
38
39
 
39
40
  def call
41
+ raise Startback::Errors::InternalServerError, "Something bad happened" if input.crash
40
42
  input.message
41
43
  end
42
44
  end
@@ -64,10 +64,11 @@ module Startback
64
64
  end
65
65
  end
66
66
 
67
- context 'when the job is ready' do
67
+ context 'when the job is ready and successful' do
68
68
  let(:override) do
69
69
  {
70
70
  isReady: true,
71
+ hasFailed: false,
71
72
  opResult: { "foo" => 'Hello!!' },
72
73
  strategy: 'Embedded'
73
74
  }
@@ -80,6 +81,30 @@ module Startback
80
81
  end
81
82
  end
82
83
 
84
+ context 'when the job failed' do
85
+ let(:override) do
86
+ {
87
+ isReady: true,
88
+ hasFailed: true,
89
+ opResult: {
90
+ errClass: 'AClass',
91
+ message: 'Something bad happened',
92
+ backtrace: ['private information'],
93
+ },
94
+ strategy: 'Embedded'
95
+ }
96
+ end
97
+
98
+ it 'works fine' do
99
+ res = subject
100
+ expect(res.status).to eql(272)
101
+ decoded = JSON.parse(res.body)
102
+ expect(decoded.keys).to eql(['errClass', 'message'])
103
+ expect(decoded['errClass']).to eql('AClass')
104
+ expect(decoded['message']).to eql('Something bad happened')
105
+ end
106
+ end
107
+
83
108
  context 'when the job is ready and has to redirect' do
84
109
  let(:override) do
85
110
  {
@@ -17,6 +17,18 @@ module Startback
17
17
  expect(job[:id]).to eql('abcdef')
18
18
  expect(job.ready?).to eql(false)
19
19
  end
20
+
21
+ it 'recognizes failed jobs' do
22
+ job = Job.full(a_job_data.merge(hasFailed: true))
23
+ expect(job.id).to eql('abcdef')
24
+ expect(job.failed?).to eql(true)
25
+ end
26
+
27
+ it 'stays compatible with jobs without the hasFailed flag' do
28
+ job = Job.full(a_job_data.delete_if{|k| k == :hasFailed })
29
+ expect(job.id).to eql('abcdef')
30
+ expect(job.failed?).to eql(false)
31
+ end
20
32
  end
21
33
  end
22
34
  end
@@ -4,10 +4,6 @@ module Startback
4
4
  module Jobs
5
5
  describe RunJob do
6
6
 
7
- let(:job_data) do
8
- a_job_data
9
- end
10
-
11
7
  let(:jobs_relvar) do
12
8
  Bmg.mutable([job_data])
13
9
  end
@@ -22,16 +18,42 @@ module Startback
22
18
  }).call
23
19
  end
24
20
 
25
- it 'runs the job' do
26
- expect(subject).to eql('Hello !!')
21
+ describe 'When job runs successfuly' do
22
+
23
+ let(:job_data) do
24
+ a_job_data
25
+ end
26
+
27
+ it 'runs the job' do
28
+ expect(subject).to eql('Hello !!')
29
+ end
30
+
31
+ it 'updates the job' do
32
+ subject
33
+ job_info = jobs_relvar.one
34
+ expect(job_info[:opResult]).to eql('Hello !!')
35
+ expect(job_info[:isReady]).to eql(true)
36
+ end
27
37
  end
28
38
 
29
- it 'updates the job' do
30
- subject
31
- job_info = jobs_relvar.one
32
- expect(job_info[:opResult]).to eql('Hello !!')
33
- expect(job_info[:isReady]).to eql(true)
39
+ describe 'When job fails' do
40
+
41
+ let(:job_data) do
42
+ a_job_data({
43
+ opInput: { 'crash' => true },
44
+ })
45
+ end
46
+
47
+ it 'updates the job' do
48
+ subject
49
+ job_info = jobs_relvar.one
50
+ expect(job_info[:isReady]).to eql(true)
51
+ expect(job_info[:opResult][:errClass]).to eql('Startback::Errors::InternalServerError')
52
+ expect(job_info[:opResult][:message]).to eql('Something bad happened')
53
+ expect(job_info[:opResult][:backtrace]).to be_a(Array)
54
+ end
34
55
  end
56
+
35
57
  end
36
58
  end
37
59
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: startback-jobs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.4
4
+ version: 0.15.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernard Lambeau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-13 00:00:00.000000000 Z
11
+ date: 2023-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -118,14 +118,14 @@ dependencies:
118
118
  requirements:
119
119
  - - '='
120
120
  - !ruby/object:Gem::Version
121
- version: 0.15.4
121
+ version: 0.15.5
122
122
  type: :runtime
123
123
  prerelease: false
124
124
  version_requirements: !ruby/object:Gem::Requirement
125
125
  requirements:
126
126
  - - '='
127
127
  - !ruby/object:Gem::Version
128
- version: 0.15.4
128
+ version: 0.15.5
129
129
  description: Asynchronous jobs on top of the Startback framework
130
130
  email: blambeau@gmail.com
131
131
  executables: []
@@ -181,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
181
181
  - !ruby/object:Gem::Version
182
182
  version: '0'
183
183
  requirements: []
184
- rubygems_version: 3.1.2
184
+ rubygems_version: 3.3.5
185
185
  signing_key:
186
186
  specification_version: 4
187
187
  summary: Asynchronous jobs on top of Startback