active_job_store 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 913b4d81b0dfb938f013f907696dc04354a106818140d25003ae44ab4e4ed9f9
4
- data.tar.gz: 39874892b9ee2443311d54cfedf7589697959c5ccb4184d8d934d67960838c7d
3
+ metadata.gz: a9fd49a85e50473450a09a741acaf01d5e6565116cb6f945f314bd6e4dd74f6d
4
+ data.tar.gz: d5655ec674b4a86d99b267c8a851e2a8d1cd687e188c58c8a292bf5120cffc3b
5
5
  SHA512:
6
- metadata.gz: 18b9c5696a4b4092ae9ea5d6ae8ed74ed45aaef567804f53a7b59fee306038f6ce2e63f0832b9bdc6f6ad61dbb7d69b81239c5801fe39db2b163be50f0e468ad
7
- data.tar.gz: 0ad46829f63b6a6347812df19f0b0a3ef8b9e0c092ecf6f8f1743b08ddfeef9077735cdcb19690421222ca9557b2c6338b9e122d7e747f76a50d3357d62e3534
6
+ metadata.gz: f9e1a166e181d32afb0265ac062b954930b8d748af36b21e837d2ee6fe28a7d57edc2f9ad590339e49fefbc3256e6b43317d19ab4e9ff1de36e7f2aa67d0dac4
7
+ data.tar.gz: a407a4446dec032e4bf6f7b5f55536dadd703c0d1d1a75d61cdf37ace3388e09c836c520ffde6c0b31043867bd92c82ad04c57b54d7398ca126baa080715e0a5
data/README.md CHANGED
@@ -7,14 +7,11 @@
7
7
  Persist job execution information on a support model `ActiveJobStore::Record`.
8
8
 
9
9
  It can be useful to:
10
- - improve jobs logging capabilities;
11
- - query historical data about job executions;
12
- - extract job's statistical data;
13
- - track a job's state / set progress value / add custom data to the jobs.
10
+ - store the job's state / set progress value / add custom data to the jobs;
11
+ - query historical data about job executions / extract job's statistical data;
12
+ - improve jobs' logging capabilities.
14
13
 
15
- Support some customizations:
16
- - set custom data attributes (via `active_job_store_custom_data` accessor);
17
- - format the job result to store (overriding `active_job_store_format_result` method).
14
+ Please if you like it.
18
15
 
19
16
  ## Installation
20
17
 
@@ -24,6 +21,19 @@ Support some customizations:
24
21
  - Add to your job `include ActiveJobStore` (or to your `ApplicationJob` class if you prefer)
25
22
  - Access to the job executions data using the class method `job_executions` on your job (ex. `YourJob.job_executions`)
26
23
 
24
+ ## API
25
+
26
+ attr_accessor on the jobs:
27
+ - `active_job_store_custom_data`: to set / manipulate job's custom data
28
+
29
+ Instance methods on the jobs:
30
+ - `active_job_store_format_result(result) => result2`: to format / manipulate / serialize the job result
31
+ - `active_job_store_record => store record`: returns the store's record
32
+ - `save_job_custom_data(custom_data = nil)`: to persist custom data while the job is performing
33
+
34
+ Class methods on the jobs:
35
+ - `job_executions => relation`: query the list of job executions for the specific job class (returns an ActiveRecord Relation)
36
+
27
37
  ## Usage examples
28
38
 
29
39
  ```rb
@@ -48,18 +58,6 @@ SomeJob.job_executions.first
48
58
  # created_at: Wed, 09 Nov 2022 21:09:50.611900000 UTC +00:00>
49
59
  ```
50
60
 
51
- Extract some logs:
52
-
53
- ```rb
54
- puts ::ActiveJobStore::Record.order(id: :desc).pluck(:created_at, :job_class, :arguments, :state, :completed_at).map { _1.join(', ') }
55
- # 2022-11-09 21:20:57 UTC, SomeJob, 123, completed, 2022-11-09 21:20:58 UTC
56
- # 2022-11-09 21:18:26 UTC, AnotherJob, another test 2, completed, 2022-11-09 21:18:26 UTC
57
- # 2022-11-09 21:13:18 UTC, SomeJob, Some test 3, completed, 2022-11-09 21:13:19 UTC
58
- # 2022-11-09 21:12:18 UTC, SomeJob, Some test 2, error,
59
- # 2022-11-09 21:10:13 UTC, AnotherJob, another test, completed, 2022-11-09 21:10:13 UTC
60
- # 2022-11-09 21:09:50 UTC, SomeJob, Some test, completed, 2022-11-09 21:09:50 UTC
61
- ```
62
-
63
61
  Query jobs in a specific range of time:
64
62
 
65
63
  ```rb
@@ -77,7 +75,34 @@ SomeJob.job_executions.completed.map { |job| { id: job.id, execution_time: job.c
77
75
  # {:id=>1, :execution_time=>0.011442, :started_at=>Wed, 09 Nov 2022 21:09:50.611355000 UTC +00:00}]
78
76
  ```
79
77
 
80
- ## Customizations
78
+ Extract some logs:
79
+
80
+ ```rb
81
+ puts ::ActiveJobStore::Record.order(id: :desc).pluck(:created_at, :job_class, :arguments, :state, :completed_at).map { _1.join(', ') }
82
+ # 2022-11-09 21:20:57 UTC, SomeJob, 123, completed, 2022-11-09 21:20:58 UTC
83
+ # 2022-11-09 21:18:26 UTC, AnotherJob, another test 2, completed, 2022-11-09 21:18:26 UTC
84
+ # 2022-11-09 21:13:18 UTC, SomeJob, Some test 3, completed, 2022-11-09 21:13:19 UTC
85
+ # 2022-11-09 21:12:18 UTC, SomeJob, Some test 2, error,
86
+ # 2022-11-09 21:10:13 UTC, AnotherJob, another test, completed, 2022-11-09 21:10:13 UTC
87
+ # 2022-11-09 21:09:50 UTC, SomeJob, Some test, completed, 2022-11-09 21:09:50 UTC
88
+ ```
89
+
90
+ Query information from a job (even when it's performing):
91
+
92
+ ```rb
93
+ job = SomeJob.perform_later 123
94
+ job.active_job_store_record.slice(:job_id, :job_class, :arguments)
95
+ # => {"job_id"=>"b009f7c7-a264-4fb5-a1f8-68a8141f323b", "job_class"=>"SomeJob", "arguments"=>[123]}
96
+
97
+ job = AnotherJob.perform_later 456
98
+ job.active_job_store_record.custom_data
99
+ # => {"progress"=>0.5}
100
+ ### After a while:
101
+ job.active_job_store_record.reload.custom_data
102
+ # => {"progress"=>1.0}
103
+ ```
104
+
105
+ ## Features' details
81
106
 
82
107
  To store the custom data (ex. a progress value):
83
108
 
@@ -100,7 +125,7 @@ AnotherJob.perform_later(456)
100
125
  AnotherJob.job_executions.last.custom_data['progress'] # 1.0 (at the end)
101
126
  ```
102
127
 
103
- If you need to manipulate the custom data, there is the `active_job_store_custom_data` accessor:
128
+ To manipulate the custom data, there is the `active_job_store_custom_data` accessor:
104
129
 
105
130
  ```rb
106
131
  class AnotherJob < ApplicationJob
@@ -123,7 +148,7 @@ AnotherJob.job_executions.last.custom_data
123
148
  # => [{"time"=>"2022-11-09T21:20:57.580Z", "message"=>"SomeJob step 1"}, {"time"=>"2022-11-09T21:20:58.581Z", "message"=>"SomeJob step 2"}]
124
149
  ```
125
150
 
126
- If for any reason it's needed to process the result before storing it, just override `active_job_store_format_result`:
151
+ To process the result before storing it (ex. for serialization), override `active_job_store_format_result`:
127
152
 
128
153
  ```rb
129
154
  class AnotherJob < ApplicationJob
@@ -6,14 +6,36 @@ module ActiveJobStore
6
6
 
7
7
  attr_reader :record
8
8
 
9
+ def around_enqueue(job)
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
13
+ job_enqueued!
14
+ end
15
+
16
+ def around_perform(job)
17
+ prepare_record_on_perform(job)
18
+ job_started!
19
+ result = yield
20
+ formatted_result = job.active_job_store_format_result(result)
21
+ job_competed!(custom_data: job.active_job_store_custom_data, result: formatted_result)
22
+ rescue StandardError => e
23
+ job_failed!(exception: e, custom_data: job.active_job_store_custom_data)
24
+ raise
25
+ end
26
+
27
+ def update_job_custom_data(custom_data)
28
+ record.update!(custom_data: custom_data)
29
+ end
30
+
31
+ private
32
+
9
33
  def job_competed!(result:, custom_data:)
10
34
  record.update!(state: :completed, completed_at: Time.current, result: result, custom_data: custom_data)
11
35
  record
12
36
  end
13
37
 
14
38
  def job_enqueued!
15
- record.lock! # NOTE: needed to avoid update conflicts with perform when setting the state to enqueued
16
- yield
17
39
  record.update!(state: :enqueued, enqueued_at: Time.current)
18
40
  record
19
41
  end
@@ -44,12 +66,6 @@ module ActiveJobStore
44
66
  record
45
67
  end
46
68
 
47
- def update_job_custom_data(custom_data)
48
- record.update!(custom_data: custom_data)
49
- end
50
-
51
- private
52
-
53
69
  def record_reference(job)
54
70
  {
55
71
  job_id: job.job_id,
@@ -2,6 +2,6 @@
2
2
 
3
3
  # :nocov:
4
4
  module ActiveJobStore
5
- VERSION = '0.2.0'
5
+ VERSION = '0.3.0'
6
6
  end
7
7
  # :nocov:
@@ -4,47 +4,56 @@ require_relative 'active_job_store/engine'
4
4
  require_relative 'active_job_store/store'
5
5
 
6
6
  module ActiveJobStore
7
+ # Set / manipulate job's custom data
7
8
  attr_accessor :active_job_store_custom_data
8
9
 
9
- class << self
10
- def included(base)
11
- base.extend(ClassMethods)
12
-
13
- base.around_enqueue do |job, block|
14
- store.prepare_record_on_enqueue(job)
15
- store.job_enqueued! do
16
- block.call
17
- end
18
- end
19
-
20
- base.around_perform do |job, block|
21
- store.prepare_record_on_perform(job)
22
- store.job_started!
23
- result = block.call
24
- formatted_result = job.active_job_store_format_result(result)
25
- store.job_competed!(custom_data: active_job_store_custom_data, result: formatted_result)
26
- rescue StandardError => e
27
- store.job_failed!(exception: e, custom_data: active_job_store_custom_data)
28
- raise
29
- end
30
- end
31
- end
32
-
10
+ # Format / manipulate / serialize the job result
11
+ #
12
+ # @param result [any] Job's return value
13
+ #
14
+ # @return [any] Processed job's return value
33
15
  def active_job_store_format_result(result)
34
16
  result
35
17
  end
36
18
 
19
+ # Persist custom data while the job is performing
20
+ #
21
+ # @param custom_data [any] Attributes to serialize (it must be serializable in JSON)
37
22
  def save_job_custom_data(custom_data = nil)
38
23
  self.active_job_store_custom_data = custom_data if custom_data
39
24
  store.update_job_custom_data(active_job_store_custom_data)
40
25
  end
41
26
 
27
+ # Return the associated Active Job Store record
28
+ #
29
+ # @return [ActiveJobStore::Record] the corresponding record
30
+ def active_job_store_record
31
+ store.record
32
+ end
33
+
42
34
  module ClassMethods
35
+ # Query the list of job executions for the current job class
36
+ #
37
+ # @return [ActiveRecord Relation] query result
43
38
  def job_executions
44
39
  ::ActiveJobStore::Record.where(job_class: to_s)
45
40
  end
46
41
  end
47
42
 
43
+ class << self
44
+ def included(base)
45
+ base.extend(ClassMethods)
46
+
47
+ base.around_enqueue do |job, block|
48
+ store.around_enqueue(job) { block.call }
49
+ end
50
+
51
+ base.around_perform do |job, block|
52
+ store.around_perform(job) { block.call }
53
+ end
54
+ end
55
+ end
56
+
48
57
  private
49
58
 
50
59
  def store
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.2.0
4
+ version: 0.3.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-12 00:00:00.000000000 Z
11
+ date: 2022-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '6.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '6.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '6.0'
27
41
  description: ActiveJob Store permits to store jobs state and custom data on a database
28
42
  email: mat@blocknot.es
29
43
  executables: []