activejob-status 0.4.1 → 0.5.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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +22 -0
  3. data/README.md +420 -0
  4. data/lib/activejob-status/version.rb +1 -1
  5. metadata +164 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a8a41508ce07744c1b0372a313f3d47a981986145423b5ded100bd1f39b3b37d
4
- data.tar.gz: 6dea6ede3e4f251a637ecf5ff7dc1c824145fb7bd2a55edb4f38bfed409f74fe
3
+ metadata.gz: fa875564067c50989a462e58c7dc6cda721f9c737d90555842a45ff45c26a39a
4
+ data.tar.gz: 4275fd985ad9007cbbb841bee0e6a6f3eace42baacb4609ecedbc04883388bf9
5
5
  SHA512:
6
- metadata.gz: 4eab47f16733e16c9006ce3dff76d239ffdf2932e47bcd8eafe30c953d1131292f9fee1f4298f5f642461394f4cb7f1f41407fa8d922a4b1486a34a71f7e32f1
7
- data.tar.gz: 9fb5a5f0fc42f5c90b1a8839b856317a7f7544555dfda2e94798ad08fefeb223491b15743af8dcb3df0659351f072f27aaabfc04f7ee82a8ed5b60d56ed2b6fc
6
+ metadata.gz: 004c5a2e04dc3f780a97737531becd4baeee68d453283d07e6826c4712a54e9cbec151500e7c1dd8cf0e1561b9e319668ae469989999769bedd2d256ffb16af9
7
+ data.tar.gz: 4f6e55367525b445d13b2b524f55913cc57cf871dc4407001ce32cc8e0a4ee92b8fc28284471fe0525f77a2782afb505cbc14a13f53d4026ba56eb3b40180972
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2023 Savater Sebastien
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,420 @@
1
+ # ActiveJob::Status
2
+
3
+ Simple monitoring status for ActiveJob, independent of your queuing backend or cache storage.
4
+
5
+ [![Gem Version](https://badge.fury.io/rb/activejob-status.svg)](https://rubygems.org/gems/activejob-status)
6
+ [![CI Status](https://github.com/inkstak/activejob-status/actions/workflows/ci.yml/badge.svg)](https://github.com/inkstak/activejob-status/actions/workflows/ci.yml)
7
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
8
+ [![Maintainability](https://api.codeclimate.com/v1/badges/a7b1ec1d3769e49021fd/maintainability)](https://codeclimate.com/github/inkstak/activejob-status/maintainability)
9
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/a7b1ec1d3769e49021fd/test_coverage)](https://codeclimate.com/github/inkstak/activejob-status/test_coverage)
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ gem install activejob-status
15
+ ```
16
+ or
17
+ ```bash
18
+ bundle add activejob-status
19
+ ```
20
+
21
+ ## Dependencies
22
+
23
+ This is a legacy branch of `ActiveJob::Status` to support [EOL versions](https://endoflife.date/rails) of `ActiveJob` & `ActiveSupport`.
24
+
25
+ This version works with `ActiveSupport >= 5.0` but requires `ruby < 3.0`.
26
+
27
+
28
+ ## Configuration
29
+
30
+ ### Cache Store
31
+
32
+ By default, ActiveJob::Status use the <code>Rails.cache</code> to store data.
33
+ You can use any compatible ActiveSupport::Cache::Store you want (memory, memcache, redis, ..)
34
+ or any storage responding to <code>read/write/delete</code>
35
+
36
+ > **Note** : `Rails.cache` defaults to `ActiveSupport::Cache::NullStore` which will result in empty status.
37
+ Setting a cache store for ActiveJob::Status is therefore mandatory.
38
+
39
+ You can set your own store:
40
+
41
+ ```ruby
42
+ # config/initializers/activejob_status.rb
43
+
44
+ # Use an alternative cache store:
45
+ # ActiveJob::Status.store = :file_store, "/path/to/cache/directory"
46
+ # ActiveJob::Status.store = :redis_cache_store, { url: ENV['REDIS_URL'] }
47
+ # ActiveJob::Status.store = :mem_cache_store
48
+ #
49
+ # You should avoid using cache store that are not shared between web and background processes
50
+ # (ex: :memory_store).
51
+ #
52
+ if Rails.cache.is_a?(ActiveSupport::Cache::NullStore)
53
+ ActiveJob::Status.store = :mem_cache_store
54
+ end
55
+ ```
56
+
57
+ ### Select data to store by default
58
+
59
+ By default, ActiveJob::Status already stores a status key at each step of a job's life cycle.
60
+ To understand what data are stored and what data to add, see [Data stored by default](#data-stored-by-default).
61
+
62
+ > **Warning** : adding more data means more memory consumed.
63
+ > For example, adding `:serialized_job` might require as much memory for caching as your use for your job backend.
64
+
65
+ ```ruby
66
+ # config/initializers/activejob_status.rb
67
+
68
+ # Select what data you want to store.
69
+ # Available options are: :status, :serialized_job, :exception
70
+ # Default is [:status]
71
+ #
72
+ ActiveJob::Status.options = { includes: %i[status exception] }
73
+ ```
74
+
75
+ ### Expiration time
76
+
77
+ Because ActiveJob::Status relies on cache store, all statuses come with an expiration time.
78
+ It's set to 1 hour by default.
79
+
80
+ You can set a longer expiration:
81
+
82
+ ```ruby
83
+ # config/initializers/activejob_status.rb
84
+
85
+ # Set your own status expiration time:
86
+ # Default is 1 hour.
87
+ #
88
+ ActiveJob::Status.options = { expires_in: 30.days.to_i }
89
+ ```
90
+
91
+ ### Throttling
92
+
93
+ Depending on the cache storage latency, updating a status too often can cause bottlenecks.
94
+ To narrow this effect, you can force a time interval between each updates:
95
+
96
+ ```ruby
97
+ # config/initializers/activejob_status.rb
98
+
99
+ # Apply a time interval in seconds between every status updates.
100
+ # Default is 0 - no throttling mechanism
101
+ #
102
+ ActiveJob::Status.options = { throttle_interval: 0.1 }
103
+ ```
104
+
105
+
106
+ ## Usage
107
+
108
+ ### Updating status
109
+
110
+ Include the <code>ActiveJob::Status</code> module in your jobs.
111
+
112
+ ```ruby
113
+ class MyJob < ActiveJob::Base
114
+ include ActiveJob::Status
115
+ end
116
+ ```
117
+
118
+ The module introduces two methods:
119
+
120
+ * <code>progress</code> to implement a progress status
121
+
122
+ ```ruby
123
+ class MyJob < ActiveJob::Base
124
+ include ActiveJob::Status
125
+
126
+ def perform
127
+ progress.total = 1000
128
+
129
+ 1000.time do
130
+ # ...do something...
131
+ progress.increment
132
+ end
133
+ end
134
+ end
135
+ ```
136
+
137
+ * <code>status</code> to directly read/update status
138
+
139
+ ```ruby
140
+ class MyJob < ActiveJob::Base
141
+ include ActiveJob::Status
142
+
143
+ def perform
144
+ status[:step] = "A"
145
+
146
+ # ...do something...
147
+
148
+ status[:step] = "B"
149
+ status[:result] = "...."
150
+ end
151
+ end
152
+ ```
153
+
154
+ You can combine both to update status and progress in a single call.
155
+
156
+ ```ruby
157
+ class MyJob < ActiveJob::Base
158
+ include ActiveJob::Status
159
+
160
+ def perform
161
+ status.update(step: "A", total: 100)
162
+
163
+ 100.times do
164
+ # ...do something...
165
+ progress.increment
166
+ end
167
+
168
+ # Reset the progress for the next step
169
+ status.update(step: "B", total: 50, progress: 0)
170
+
171
+ 50.times do
172
+ # ...do something...
173
+ progress.increment
174
+ end
175
+ end
176
+ end
177
+ ```
178
+
179
+ Throttling mechanism (see configuration) is applied when doing:
180
+
181
+ ```ruby
182
+ progress.increment
183
+ progress.decrement
184
+ status.update(foo: 'bar')
185
+ ```
186
+
187
+ Throttling mechanism is not applied when doing:
188
+
189
+ ```ruby
190
+ progress.total = 100
191
+ progress.progress = 0
192
+ progress.finish
193
+ status[:foo] = 'bar'
194
+ status.update({ foo: 'bar' }, force: true)
195
+ ```
196
+
197
+ ### Data stored by default
198
+
199
+ By default, ActiveJob::Status stores a status key.
200
+ You can add more information about the job using `includes` config.
201
+
202
+ Setting `ActiveJob::Status.options = { includes: %i[status] }` is equivalent to:
203
+
204
+ ```ruby
205
+ before_enqueue { |job| job.status[:status] = :queued }
206
+ before_perform { |job| job.status[:status] = :working }
207
+ after_perform { |job| job.status[:status] = :completed }
208
+
209
+ rescue_from(Exception) do |e|
210
+ status[:status] = :failed
211
+ raise e
212
+ end
213
+ ```
214
+
215
+ Setting `ActiveJob::Status.options = { includes: %i[serialized_job] }` is equivalent to:
216
+
217
+ ```ruby
218
+ before_enqueue { |job| job.status[:serialized_job] = job.serialize }
219
+ ```
220
+
221
+ Setting `ActiveJob::Status.options = { includes: %i[exception] }` is equivalent to:
222
+
223
+ ```ruby
224
+ rescue_from(Exception) do |e|
225
+ status[:exception] = { class: e.class, message: e.message }
226
+ raise e
227
+ end
228
+ ```
229
+
230
+ ### Reading status
231
+
232
+ Check the status of a job
233
+
234
+ ```ruby
235
+ job = MyJob.perform_later
236
+ status = ActiveJob::Status.get(job)
237
+ # => { status: :queued }
238
+ ```
239
+
240
+ You can also use the job_id
241
+
242
+ ```ruby
243
+ status = ActiveJob::Status.get('d11b64e6-8631-4118-ae76-e19376769171')
244
+ # => { status: :queued }
245
+ ```
246
+
247
+ Follow the progression of your job
248
+
249
+ ```ruby
250
+ loop do
251
+ puts status
252
+ break if status.completed?
253
+ end
254
+
255
+ # => { status: :queued }
256
+ # => { status: :working, progress: 0, total: 100, step: "A" }
257
+ # => { status: :working, progress: 60, total: 100, step: "A" }
258
+ # => { status: :working, progress: 90, total: 100, step: "A" }
259
+ # => { status: :working, progress: 0, total: 50, step: "B" }
260
+ # => { status: :completed, progress: 50, total: 50, step: "B" }
261
+ ```
262
+
263
+ The status provides you getters:
264
+
265
+ ```ruby
266
+ status.status # => "working"
267
+ status.queued? # => false
268
+ status.working? # => true
269
+ status.completed? # => false
270
+ status.failed? # => false
271
+ status.progress # => 0.5 (progress / total)
272
+ status[:step] # => "A"
273
+ ```
274
+
275
+ ... until it's completed
276
+
277
+ ```ruby
278
+ status.status # => "completed"
279
+ status.completed? # => true
280
+ status.progress # => 1
281
+ ```
282
+
283
+ ### Serializing status to JSON
284
+
285
+ Within a controller, you can serialize a status to JSON:
286
+
287
+ ```ruby
288
+ class JobsController
289
+ def show
290
+ status = ActiveJob::Status.get(params[:id])
291
+ render json: status.to_json
292
+ end
293
+ end
294
+ ```
295
+
296
+ ```
297
+ GET /jobs/status/d11b64e6-8631-4118-ae76-e19376769171.json
298
+
299
+ {
300
+ "status": "working",
301
+ "progress": 50
302
+ "total": 100,
303
+ "step": "A"
304
+ }
305
+ ```
306
+
307
+ ### Setting options per job
308
+
309
+ You can override default options per job:
310
+
311
+ ```ruby
312
+ class MyJob < ActiveJob::Base
313
+ include ActiveJob::Status
314
+
315
+ def status
316
+ @status ||= ActiveJob::Status::Status.new(self,
317
+ expires_in: 3.days,
318
+ throttle_interval: 0.5,
319
+ includes: %i[status serialized_job])
320
+ end
321
+
322
+ def perform
323
+ ...
324
+ end
325
+ end
326
+ ```
327
+
328
+ ## ActiveJob::Status and exceptions
329
+
330
+ Internally, ActiveJob::Status uses `ActiveSupport#rescue_from` to catch every `Exception` to apply the `failed` status
331
+ before throwing the exception again.
332
+
333
+ [Rails](https://api.rubyonrails.org/classes/ActiveSupport/Rescuable/ClassMethods.html#method-i-rescue_from) says:
334
+ > Handlers are inherited. They are searched from right to left, from bottom to top, and up the hierarchy. The handler of
335
+ the first class for which exception.is_a?(klass) holds true is the one invoked, if any.
336
+
337
+ Thus, there are a few points to consider when using `rescue_from`:
338
+
339
+ 1 - Do not declare `rescue_from` handlers before including `ActiveJob::Status`. They cannot be called:
340
+
341
+ ```ruby
342
+ class ApplicationJob < ActiveJob::Base
343
+ rescue_from Exception do |e|
344
+ ExceptionMonitoring.notify(e)
345
+ raise e
346
+ end
347
+ end
348
+
349
+ class MyJob < ApplicationJob
350
+ # The rescue handlers from ApplicationJob won't ever be executed
351
+ # and the exception monitoring won't be notified.
352
+
353
+ include ActiveJob::Status
354
+ end
355
+ ```
356
+
357
+ 2 - If you're rescuing any or all exceptions, the status will never be set to `failed`. You need to update it by
358
+ yourself:
359
+
360
+ ```ruby
361
+ class ApplicationJob < ActiveJob::Base
362
+ include ActiveJob::Status
363
+
364
+ rescue_from Exception do |e|
365
+ ExceptionMonitoring.notify(e)
366
+ status.catch_exception(e)
367
+ raise e
368
+ end
369
+ end
370
+ ```
371
+
372
+ 3 - Subsequent handlers will stop the rescuing mechanism:
373
+
374
+ ```ruby
375
+ class MyJob < ApplicationJob
376
+ # With the exceptions handled below:
377
+ # - the monitor won't be notified
378
+ # - the job status will remains to `working`
379
+
380
+ retry_on 'SomeTimeoutError', wait: 5.seconds
381
+ discard_on 'DeserializationError'
382
+ rescue_from 'AnotherCustomException' do |e|
383
+ do_something_else
384
+ end
385
+ end
386
+ ```
387
+
388
+ ## Contributing
389
+
390
+ 1. Don't hesitate to submit your feature/idea/fix in [issues](https://github.com/inkstak/activejob-status)
391
+ 2. Fork the [repository](https://github.com/inkstak/activejob-status)
392
+ 3. Create your feature branch
393
+ 4. Ensure RSpec & Rubocop are passing
394
+ 4. Create a pull request
395
+
396
+ ### Tests & lint
397
+
398
+ ```bash
399
+ bundle exec rspec
400
+ bundle exec rubocop
401
+ bundle exec standardrb
402
+ ```
403
+
404
+ All of them can be run with:
405
+
406
+ ```bash
407
+ bundle exec rake
408
+ ```
409
+
410
+ To run test suite against various version of Rails dependencies:
411
+ ```bash
412
+ bundle exec appraisal install
413
+ bundle exec appraisal
414
+ ```
415
+
416
+ ## License & credits
417
+
418
+ Please see [LICENSE](https://github.com/inkstak/coverart/blob/main/LICENSE) for further details.
419
+
420
+ Contributors: [./graphs/contributors](https://github.com/inkstak/coverart/graphs/contributors)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ActiveJob
4
4
  module Status
5
- VERSION = "0.4.1"
5
+ VERSION = "0.5.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activejob-status
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Savater Sebastien
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-30 00:00:00.000000000 Z
11
+ date: 2023-03-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -16,35 +16,188 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '4.2'
19
+ version: '5.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '6'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - ">="
25
28
  - !ruby/object:Gem::Version
26
- version: '4.2'
29
+ version: '5.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '6'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: activesupport
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - ">="
32
38
  - !ruby/object:Gem::Version
33
- version: '4.2'
39
+ version: '5.0'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '6'
34
43
  type: :runtime
35
44
  prerelease: false
36
45
  version_requirements: !ruby/object:Gem::Requirement
37
46
  requirements:
38
47
  - - ">="
39
48
  - !ruby/object:Gem::Version
40
- version: '4.2'
49
+ version: '5.0'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '6'
53
+ - !ruby/object:Gem::Dependency
54
+ name: appraisal
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ - !ruby/object:Gem::Dependency
68
+ name: rake
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ - !ruby/object:Gem::Dependency
82
+ name: rspec
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: rubocop
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ - !ruby/object:Gem::Dependency
110
+ name: rubocop-rake
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ - !ruby/object:Gem::Dependency
124
+ name: rubocop-rspec
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ - !ruby/object:Gem::Dependency
138
+ name: rubocop-performance
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ - !ruby/object:Gem::Dependency
152
+ name: simplecov
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ type: :development
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ - !ruby/object:Gem::Dependency
166
+ name: standard
167
+ requirement: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ type: :development
173
+ prerelease: false
174
+ version_requirements: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ - !ruby/object:Gem::Dependency
180
+ name: timecop
181
+ requirement: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ type: :development
187
+ prerelease: false
188
+ version_requirements: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: '0'
41
193
  description:
42
- email:
43
- - savater.sebastien@gmail.com
194
+ email: github.60k5k@simplelogin.co
44
195
  executables: []
45
196
  extensions: []
46
197
  extra_rdoc_files: []
47
198
  files:
199
+ - LICENSE
200
+ - README.md
48
201
  - lib/activejob-status.rb
49
202
  - lib/activejob-status/progress.rb
50
203
  - lib/activejob-status/status.rb
@@ -61,16 +214,16 @@ require_paths:
61
214
  - lib
62
215
  required_ruby_version: !ruby/object:Gem::Requirement
63
216
  requirements:
64
- - - ">="
217
+ - - "<"
65
218
  - !ruby/object:Gem::Version
66
- version: '0'
219
+ version: '3'
67
220
  required_rubygems_version: !ruby/object:Gem::Requirement
68
221
  requirements:
69
222
  - - ">="
70
223
  - !ruby/object:Gem::Version
71
224
  version: '0'
72
225
  requirements: []
73
- rubygems_version: 3.3.7
226
+ rubygems_version: 3.1.6
74
227
  signing_key:
75
228
  specification_version: 4
76
229
  summary: Monitor your jobs