active_job_store 0.3.0 → 0.5.0

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: a9fd49a85e50473450a09a741acaf01d5e6565116cb6f945f314bd6e4dd74f6d
4
- data.tar.gz: d5655ec674b4a86d99b267c8a851e2a8d1cd687e188c58c8a292bf5120cffc3b
3
+ metadata.gz: 2a53200d7e5f4f9654d3e8db62ef8a92014a78d264f43cece9486228a3ff03c9
4
+ data.tar.gz: b703fe5f1183d8c0718eb45e651580f02d41d0efae9eb81cc9e1a59c10e788a4
5
5
  SHA512:
6
- metadata.gz: f9e1a166e181d32afb0265ac062b954930b8d748af36b21e837d2ee6fe28a7d57edc2f9ad590339e49fefbc3256e6b43317d19ab4e9ff1de36e7f2aa67d0dac4
7
- data.tar.gz: a407a4446dec032e4bf6f7b5f55536dadd703c0d1d1a75d61cdf37ace3388e09c836c520ffde6c0b31043867bd92c82ad04c57b54d7398ca126baa080715e0a5
6
+ metadata.gz: 819a6339762b27117d43cf52075896611c5e83818018546a04c0727a03daad4f3a77b60c71030ef8218940ea1883223b4bf016b2a3e787f9b4fd810c2ded8f6b
7
+ data.tar.gz: a1bcf57d7b6f670dd90231abc21ed241a532a8ad7985b6e68b40b4b3c29001f8a23408f676ac4c0b45fb81e3102f33b8b2e3e7a9089add9410eb710465607cc0
data/README.md CHANGED
@@ -11,6 +11,8 @@ It can be useful to:
11
11
  - query historical data about job executions / extract job's statistical data;
12
12
  - improve jobs' logging capabilities.
13
13
 
14
+ By default gem's internal errors are sent to stderr without compromising the job's perform.
15
+
14
16
  Please ⭐ if you like it.
15
17
 
16
18
  ## Installation
@@ -28,6 +30,7 @@ attr_accessor on the jobs:
28
30
 
29
31
  Instance methods on the jobs:
30
32
  - `active_job_store_format_result(result) => result2`: to format / manipulate / serialize the job result
33
+ - `active_job_store_internal_error(context, exception)`: handler for internal errors
31
34
  - `active_job_store_record => store record`: returns the store's record
32
35
  - `save_job_custom_data(custom_data = nil)`: to persist custom data while the job is performing
33
36
 
@@ -87,7 +90,7 @@ puts ::ActiveJobStore::Record.order(id: :desc).pluck(:created_at, :job_class, :a
87
90
  # 2022-11-09 21:09:50 UTC, SomeJob, Some test, completed, 2022-11-09 21:09:50 UTC
88
91
  ```
89
92
 
90
- Query information from a job (even when it's performing):
93
+ Query information from a job (even while performing):
91
94
 
92
95
  ```rb
93
96
  job = SomeJob.perform_later 123
@@ -102,9 +105,9 @@ job.active_job_store_record.reload.custom_data
102
105
  # => {"progress"=>1.0}
103
106
  ```
104
107
 
105
- ## Features' details
108
+ ## Features' examples
106
109
 
107
- To store the custom data (ex. a progress value):
110
+ To persist some custom data during the perform (ex. a progress value):
108
111
 
109
112
  ```rb
110
113
  class AnotherJob < ApplicationJob
@@ -125,7 +128,7 @@ AnotherJob.perform_later(456)
125
128
  AnotherJob.job_executions.last.custom_data['progress'] # 1.0 (at the end)
126
129
  ```
127
130
 
128
- To manipulate the custom data, there is the `active_job_store_custom_data` accessor:
131
+ To manipulate the custom data persisted only at the end:
129
132
 
130
133
  ```rb
131
134
  class AnotherJob < ApplicationJob
@@ -148,7 +151,7 @@ AnotherJob.job_executions.last.custom_data
148
151
  # => [{"time"=>"2022-11-09T21:20:57.580Z", "message"=>"SomeJob step 1"}, {"time"=>"2022-11-09T21:20:58.581Z", "message"=>"SomeJob step 2"}]
149
152
  ```
150
153
 
151
- To process the result before storing it (ex. for serialization), override `active_job_store_format_result`:
154
+ To process the job's result before storing it (ex. for serialization):
152
155
 
153
156
  ```rb
154
157
  class AnotherJob < ApplicationJob
@@ -169,6 +172,21 @@ AnotherJob.job_executions.last.result
169
172
  # => 84
170
173
  ```
171
174
 
175
+ To raise an exception also when there is a gem's internal error:
176
+
177
+ ```rb
178
+ class AnotherJob < ApplicationJob
179
+ include ActiveJobStore
180
+
181
+ # ...
182
+
183
+ def active_job_store_internal_error(context, exception)
184
+ raise exception
185
+ # Or simply monitor these errors using services like Sentry/Honeybadger/etc.
186
+ end
187
+ end
188
+ ```
189
+
172
190
  ## Do you like it? Star it!
173
191
 
174
192
  If you use this component just star it. A developer is more motivated to improve a project when there is some interest.
@@ -4,10 +4,10 @@ module ActiveJobStore
4
4
  class Record < ApplicationRecord
5
5
  self.table_name = 'active_job_store'
6
6
 
7
- serialize :arguments, JSON
8
- serialize :custom_data, JSON
9
- serialize :details, JSON
10
- serialize :result, JSON
7
+ serialize :arguments, coder: JSON
8
+ serialize :custom_data, coder: JSON
9
+ serialize :details, coder: JSON
10
+ serialize :result, coder: JSON
11
11
 
12
12
  enum state: { initialized: 0, enqueued: 1, started: 2, completed: 3, error: 4 }
13
13
 
@@ -8,9 +8,11 @@ module ActiveJobStore
8
8
 
9
9
  def around_enqueue(job)
10
10
  prepare_record_on_enqueue(job)
11
- record.lock! # NOTE: needed to avoid update conflicts with perform when setting the state to enqueued
12
- yield
11
+ lock_record!
12
+ result = yield
13
13
  job_enqueued!
14
+ job.active_job_store_internal_error('ActiveJobStore::Store around_enqueue', internal_error) if internal_error
15
+ result
14
16
  end
15
17
 
16
18
  def around_perform(job)
@@ -19,51 +21,71 @@ module ActiveJobStore
19
21
  result = yield
20
22
  formatted_result = job.active_job_store_format_result(result)
21
23
  job_competed!(custom_data: job.active_job_store_custom_data, result: formatted_result)
24
+ job.active_job_store_internal_error('ActiveJobStore::Store around_perform', internal_error) if internal_error
25
+ result
22
26
  rescue StandardError => e
23
27
  job_failed!(exception: e, custom_data: job.active_job_store_custom_data)
24
28
  raise
25
29
  end
26
30
 
27
31
  def update_job_custom_data(custom_data)
28
- record.update!(custom_data: custom_data)
32
+ wrap_errors do
33
+ record.update!(custom_data: custom_data)
34
+ end
29
35
  end
30
36
 
31
37
  private
32
38
 
39
+ attr_accessor :internal_error
40
+
33
41
  def job_competed!(result:, custom_data:)
34
- record.update!(state: :completed, completed_at: Time.current, result: result, custom_data: custom_data)
35
- record
42
+ wrap_errors do
43
+ record.update!(state: :completed, completed_at: Time.current, result: result, custom_data: custom_data)
44
+ end
36
45
  end
37
46
 
38
47
  def job_enqueued!
39
- record.update!(state: :enqueued, enqueued_at: Time.current)
40
- record
48
+ wrap_errors do
49
+ record.update!(state: :enqueued, enqueued_at: Time.current)
50
+ end
41
51
  end
42
52
 
43
53
  def job_failed!(exception:, custom_data:)
44
- record.update!(state: :error, exception: exception.inspect, custom_data: custom_data)
45
- record
54
+ wrap_errors do
55
+ record.update!(state: :error, exception: exception.inspect, custom_data: custom_data)
56
+ end
46
57
  end
47
58
 
48
59
  def job_started!
49
- record.update!(state: :started, started_at: Time.current)
50
- record
60
+ wrap_errors do
61
+ record.update!(state: :started, started_at: Time.current)
62
+ end
63
+ end
64
+
65
+ def lock_record!
66
+ wrap_errors do
67
+ record.lock! # NOTE: needed to avoid update conflicts with perform when setting the state to enqueued
68
+ end
51
69
  end
52
70
 
53
71
  def prepare_record_on_enqueue(job)
54
- @record = ::ActiveJobStore::Record.find_or_create_by!(record_reference(job)) do |record|
55
- record.arguments = job.arguments
56
- record.details = DETAILS_ATTRS.zip(DETAILS_ATTRS.map { job.send(_1) }).to_h
57
- record.state = :initialized
72
+ wrap_errors do
73
+ @record = ::ActiveJobStore::Record.find_or_create_by!(record_reference(job)) do |record|
74
+ record.arguments = job.arguments
75
+ record.details = DETAILS_ATTRS.zip(DETAILS_ATTRS.map { job.send(_1) }).to_h
76
+ record.state = :initialized
77
+ end
58
78
  end
59
79
  end
60
80
 
61
81
  def prepare_record_on_perform(job)
62
- @record = ::ActiveJobStore::Record.find_or_initialize_by(record_reference(job)) do |record|
63
- record.arguments = job.arguments
82
+ wrap_errors do
83
+ @record = ::ActiveJobStore::Record.find_or_initialize_by(record_reference(job)) do |record|
84
+ record.arguments = job.arguments
85
+ end
86
+ record.details = DETAILS_ATTRS.zip(DETAILS_ATTRS.map { job.send(_1) }).to_h
87
+ record
64
88
  end
65
- record.details = DETAILS_ATTRS.zip(DETAILS_ATTRS.map { job.send(_1) }).to_h
66
- record
67
89
  end
68
90
 
69
91
  def record_reference(job)
@@ -72,5 +94,13 @@ module ActiveJobStore
72
94
  job_class: job.class.to_s
73
95
  }
74
96
  end
97
+
98
+ def wrap_errors
99
+ return if internal_error
100
+
101
+ yield
102
+ rescue StandardError => e
103
+ self.internal_error = e
104
+ end
75
105
  end
76
106
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  # :nocov:
4
4
  module ActiveJobStore
5
- VERSION = '0.3.0'
5
+ VERSION = '0.5.0'
6
6
  end
7
7
  # :nocov:
@@ -31,6 +31,13 @@ module ActiveJobStore
31
31
  store.record
32
32
  end
33
33
 
34
+ # Internal errors handler method
35
+ #
36
+ # @param exception [exception] The internal exception
37
+ def active_job_store_internal_error(context, exception)
38
+ warn("#{context}: #{exception}")
39
+ end
40
+
34
41
  module ClassMethods
35
42
  # Query the list of job executions for the current job class
36
43
  #
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_job_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattia Roccoberton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-15 00:00:00.000000000 Z
11
+ date: 2023-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -58,7 +58,7 @@ licenses:
58
58
  metadata:
59
59
  homepage_uri: https://github.com/blocknotes/active_job_store
60
60
  source_code_uri: https://github.com/blocknotes/active_job_store
61
- changelog_uri: https://github.com/blocknotes/active_job_store/blob/master/CHANGELOG.md
61
+ changelog_uri: https://github.com/blocknotes/active_job_store/blob/main/CHANGELOG.md
62
62
  rubygems_mfa_required: 'true'
63
63
  post_install_message:
64
64
  rdoc_options: []
@@ -68,14 +68,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
68
68
  requirements:
69
69
  - - ">="
70
70
  - !ruby/object:Gem::Version
71
- version: 2.6.0
71
+ version: 2.7.0
72
72
  required_rubygems_version: !ruby/object:Gem::Requirement
73
73
  requirements:
74
74
  - - ">="
75
75
  - !ruby/object:Gem::Version
76
76
  version: '0'
77
77
  requirements: []
78
- rubygems_version: 3.1.6
78
+ rubygems_version: 3.4.19
79
79
  signing_key:
80
80
  specification_version: 4
81
81
  summary: Persist jobs information on DB