job_contracts 0.1.2 → 0.1.3

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: c8f52af511321598aed75762fb9b133a2f92af32365148881b9ab5834399ed64
4
- data.tar.gz: 8d1646b541bcbc1599b2d8a68d41d8b8e030c333d33acda8d1b5a473ce850a49
3
+ metadata.gz: b3ed33558c769a0bc1ef0d74e1c066b5dd3de20069d6f0ea9a37177294080969
4
+ data.tar.gz: 8d89d059123f45dfcc3ce399cb51e13e23d6f6b3b6a7c7a93d06ffd2130f8de4
5
5
  SHA512:
6
- metadata.gz: 4572323c6a8aa24eba91c36111fb8155f442d265eea89e041b36b6e66e3ddd1367acd1ba340cc79281b33d365d010127e993170b2cb7b54f8712004dce9e7ba4
7
- data.tar.gz: 66d24736ad86e8f787c2a3ea53f1c24b8d6527daa9b998f00efa4471196ebc85fee8bf01118821c3c2c9ac035c65a98f236867f44cea188f33407127dbb893be
6
+ metadata.gz: 4a575f78c5fc94884dcc453bcc4931f12dbe30f904f5cc9915d69c291cf88f82b6ec84dd0ce85067cbd6647b8db4e232b8e3ee6f0201056dc01d137a7fdf1dc3
7
+ data.tar.gz: 43ea19008133a39f25661912029c23a42523b462f9cc882a819cd989c8f5ced4bcb7046a0d1657d8b29439647335e911974c7295bcf4fcc0daa5e16d3acd96aa
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
- [![Lines of Code](http://img.shields.io/badge/lines_of_code-236-brightgreen.svg?style=flat)](http://blog.codinghorror.com/the-best-code-is-no-code-at-all/)
1
+ [![Lines of Code](http://img.shields.io/badge/lines_of_code-232-brightgreen.svg?style=flat)](http://blog.codinghorror.com/the-best-code-is-no-code-at-all/)
2
2
  [![Code Quality](https://app.codacy.com/project/badge/Grade/f604d4bc6db0474c802ef51182732488)](https://www.codacy.com/gh/hopsoft/job_contracts/dashboard?utm_source=github.com&utm_medium=referral&utm_content=hopsoft/job_contracts&utm_campaign=Badge_Grade)
3
- ![tests](https://github.com/hopsoft/job_contracts/actions/workflows/test.yml/badge.svg)
3
+ ![Tests](https://github.com/hopsoft/job_contracts/actions/workflows/test.yml/badge.svg)
4
+ [![Gem Version](https://badge.fury.io/rb/job_contracts.svg)](https://badge.fury.io/rb/job_contracts)
4
5
 
5
6
  # Job Contracts
6
7
 
@@ -47,7 +48,6 @@ class ImportantJob < ApplicationJob
47
48
  include JobContracts::Contractable
48
49
 
49
50
  queue_as :default
50
-
51
51
  add_contract JobContracts::DurationContract.new(max: 5.seconds)
52
52
 
53
53
  def perform
@@ -97,7 +97,7 @@ Contracts support the following constructor arguments.
97
97
 
98
98
  ### Defining a Contract
99
99
 
100
- Here's a contrived but simple example that ensures the first argument to perform fits within a specific range of values.
100
+ Here's a contrived, but simple, example that ensures the first argument passed to perform fits within a specific range of values.
101
101
 
102
102
  ```ruby
103
103
  # app/contracts/argument_contract.rb
@@ -203,7 +203,6 @@ class ImportantJob < ApplicationJob
203
203
  include JobContracts::Contractable
204
204
 
205
205
  queue_as :default
206
-
207
206
  on_contract_breach :take_action
208
207
  add_contract JobContracts::DurationContract.new(max: 5.seconds)
209
208
 
@@ -222,10 +221,7 @@ class ImportantJob < ApplicationJob
222
221
  include JobContracts::Contractable
223
222
 
224
223
  queue_as :default
225
-
226
- on_contract_breach -> (contract) {
227
- # take action...
228
- }
224
+ on_contract_breach -> (contract) { # take action... }
229
225
 
230
226
  add_contract JobContracts::DurationContract.new(max: 5.seconds)
231
227
 
@@ -237,11 +233,26 @@ end
237
233
 
238
234
  ## Sidekiq
239
235
 
240
- Sidekiq jobs/workers are supported.
241
- Unfortunately this support comes with a performance penalty *(i.e. additional latency)* because executing
242
- Sidekiq jobs don't have access to their own metadata. To get around this, we wait to find job metadata in the active
243
- [`WorkSet`](https://github.com/hopsoft/job_contracts/blob/main/lib/job_contracts/concerns/sidekiq_contractable.rb#L23-L25)
244
- which is only updated [every 5 seconds](https://github.com/mperham/sidekiq/wiki/API#workers).
236
+ `Sidekiq::Job`s are also supported.
237
+
238
+ ```ruby
239
+ class ImportantJob
240
+ include Sidekiq::Job
241
+ include JobContracts::SidekiqContractable
242
+
243
+ sidekiq_options queue: :default
244
+ add_contract JobContracts::DurationContract.new(max: 1.second)
245
+
246
+ def perform
247
+ # logic...
248
+ end
249
+
250
+ # default callback that's invoked if the contract is breached
251
+ def contract_breached!(contract)
252
+ # handle breach...
253
+ end
254
+ end
255
+ ```
245
256
 
246
257
  ## Todo
247
258
 
@@ -8,54 +8,32 @@ module JobContracts
8
8
  extend ActiveSupport::Concern
9
9
  include Contractable
10
10
 
11
- class SidekiqJobMetadataNotFoundError < StandardError; end
12
-
13
11
  module ClassMethods
12
+ # Matches the ActiveJob API
14
13
  def queue_name
15
14
  sidekiq_options_hash["queue"]
16
15
  end
17
16
  end
18
17
 
19
- def sidekiq_job_metadata
20
- @sidekiq_job_metadata ||= begin
21
- hit = nil
22
- begin
23
- attempts ||= 1
24
- hit = Sidekiq::Workers.new.find do |_process_id, _thread_id, work|
25
- work.dig("payload", "jid") == jid
26
- end
27
- raise SidekiqJobMetadataNotFoundError if hit.blank?
28
- rescue SidekiqJobMetadataNotFoundError
29
- # The WorkSet only updates every 5 seconds
30
- # SEE: https://github.com/mperham/sidekiq/wiki/API#workers
31
- # Re-attempt up to 10 times with a simple backoff strategy (up to 5.5 seconds)
32
- # TODO: Is there a faster and more reliable way to fetch the job's metadata after perform has begun?
33
- # May need to query Redis directly if the data is still in there at this point
34
- attempts += 1
35
- if attempts <= 10
36
- sleep 0.1 * attempts
37
- retry
38
- end
39
- end
40
-
41
- hit&.last || {}
42
- end
18
+ # Metadata used to enqueue the job
19
+ def sidekiq_job_hash
20
+ @sidekiq_job_hash ||= {}
43
21
  end
44
22
 
45
23
  # Matches the ActiveJob API
46
24
  def queue_name
47
- sidekiq_job_metadata["queue"]
25
+ sidekiq_job_hash["queue"]
48
26
  end
49
27
 
50
28
  # Matches the ActiveJob API
51
29
  def enqueued_at
52
- seconds = sidekiq_job_metadata.dig("payload", "enqueued_at")
30
+ seconds = sidekiq_job_hash["enqueued_at"]
53
31
  (seconds ? Time.at(seconds) : nil)&.iso8601.to_s
54
32
  end
55
33
 
56
34
  # Matches the ActiveJob API
57
35
  def arguments
58
- sidekiq_job_metadata.dig("payload", "args") || []
36
+ sidekiq_job_hash["args"] || []
59
37
  end
60
38
  end
61
39
  end
@@ -1,6 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "sidekiq"
4
+ require_relative "sidekiq_job_hash_middleware"
5
+
3
6
  module JobContracts
4
7
  class Railtie < ::Rails::Railtie
8
+ initializer "job_contracts.register_sidekiq_middleware" do
9
+ Sidekiq.server_middleware.add SidekiqJobHashMiddleware
10
+ end
5
11
  end
6
12
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JobContracts
4
+ class SidekiqJobHashMiddleware
5
+ def call(worker, job, _queue)
6
+ worker.instance_variable_set :@sidekiq_job_hash, job
7
+ yield
8
+ end
9
+ end
10
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JobContracts
4
- VERSION = "0.1.2"
4
+ VERSION = "0.1.3"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: job_contracts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Hopkins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-03 00:00:00.000000000 Z
11
+ date: 2022-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -126,6 +126,7 @@ files:
126
126
  - lib/job_contracts/contracts/queue_name_contract.rb
127
127
  - lib/job_contracts/contracts/read_only_contract.rb
128
128
  - lib/job_contracts/railtie.rb
129
+ - lib/job_contracts/sidekiq_job_hash_middleware.rb
129
130
  - lib/job_contracts/version.rb
130
131
  homepage: https://github.com/hopsoft/job_contracts
131
132
  licenses: