job_contracts 0.1.1 → 0.1.4
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 +4 -4
- data/README.md +26 -14
- data/lib/job_contracts/concerns/contractable.rb +0 -6
- data/lib/job_contracts/concerns/sidekiq_contractable.rb +7 -29
- data/lib/job_contracts/contracts/contract.rb +9 -9
- data/lib/job_contracts/railtie.rb +6 -0
- data/lib/job_contracts/sidekiq_job_hash_middleware.rb +10 -0
- data/lib/job_contracts/version.rb +1 -1
- metadata +11 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5bcafda35a29dbc6cb71004f638807b9634658e3eb50cd13f9ebd4274709f03c
|
4
|
+
data.tar.gz: 6a6a0e43df2db48f77525ac3ceae7bb26b36cd300becee484b65b14caec3c703
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 799d3d7aa098fe1775a7ec0e36d210ae25713ccb96c2ab5bd8962298097b7754fb5805f4c99267111aabe19f20caf47e64671806410ffd2af5c11a757121e9a1
|
7
|
+
data.tar.gz: ecef09781a6b2833d30c6e8c1ee2dcf3d32c3a500df0f1b1cab60e4cf8490eeda1b294a77263ffdc9039adec10740b68396e7d292542e75e245a405f3ec59ea0
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
[](http://blog.codinghorror.com/the-best-code-is-no-code-at-all/)
|
2
2
|
[](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
|
-

|
4
|
+
[](https://badge.fury.io/rb/job_contracts)
|
5
|
+
[](https://twitter.com/hopsoft)
|
4
6
|
|
5
7
|
# Job Contracts
|
6
8
|
|
@@ -47,7 +49,6 @@ class ImportantJob < ApplicationJob
|
|
47
49
|
include JobContracts::Contractable
|
48
50
|
|
49
51
|
queue_as :default
|
50
|
-
|
51
52
|
add_contract JobContracts::DurationContract.new(max: 5.seconds)
|
52
53
|
|
53
54
|
def perform
|
@@ -97,7 +98,7 @@ Contracts support the following constructor arguments.
|
|
97
98
|
|
98
99
|
### Defining a Contract
|
99
100
|
|
100
|
-
Here's a contrived but simple example that ensures the first argument to perform fits within a specific range of values.
|
101
|
+
Here's a contrived, but simple, example that ensures the first argument passed to perform fits within a specific range of values.
|
101
102
|
|
102
103
|
```ruby
|
103
104
|
# app/contracts/argument_contract.rb
|
@@ -203,7 +204,6 @@ class ImportantJob < ApplicationJob
|
|
203
204
|
include JobContracts::Contractable
|
204
205
|
|
205
206
|
queue_as :default
|
206
|
-
|
207
207
|
on_contract_breach :take_action
|
208
208
|
add_contract JobContracts::DurationContract.new(max: 5.seconds)
|
209
209
|
|
@@ -222,10 +222,7 @@ class ImportantJob < ApplicationJob
|
|
222
222
|
include JobContracts::Contractable
|
223
223
|
|
224
224
|
queue_as :default
|
225
|
-
|
226
|
-
on_contract_breach -> (contract) {
|
227
|
-
# take action...
|
228
|
-
}
|
225
|
+
on_contract_breach -> (contract) { # take action... }
|
229
226
|
|
230
227
|
add_contract JobContracts::DurationContract.new(max: 5.seconds)
|
231
228
|
|
@@ -237,11 +234,26 @@ end
|
|
237
234
|
|
238
235
|
## Sidekiq
|
239
236
|
|
240
|
-
Sidekiq
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
237
|
+
`Sidekiq::Job`s are also supported.
|
238
|
+
|
239
|
+
```ruby
|
240
|
+
class ImportantJob
|
241
|
+
include Sidekiq::Job
|
242
|
+
include JobContracts::SidekiqContractable
|
243
|
+
|
244
|
+
sidekiq_options queue: :default
|
245
|
+
add_contract JobContracts::DurationContract.new(max: 1.second)
|
246
|
+
|
247
|
+
def perform
|
248
|
+
# logic...
|
249
|
+
end
|
250
|
+
|
251
|
+
# default callback that's invoked if the contract is breached
|
252
|
+
def contract_breached!(contract)
|
253
|
+
# handle breach...
|
254
|
+
end
|
255
|
+
end
|
256
|
+
```
|
245
257
|
|
246
258
|
## Todo
|
247
259
|
|
@@ -75,11 +75,5 @@ module JobContracts
|
|
75
75
|
def contract_breached!
|
76
76
|
# noop / override in job subclasses
|
77
77
|
end
|
78
|
-
|
79
|
-
def on_contract_breach(contract)
|
80
|
-
breached_contracts << contract
|
81
|
-
method = self.class.on_contract_breach_callback
|
82
|
-
method.is_a?(Proc) ? method.call(contract) : send(method.to_s, contract)
|
83
|
-
end
|
84
78
|
end
|
85
79
|
end
|
@@ -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
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
25
|
+
sidekiq_job_hash["queue"]
|
48
26
|
end
|
49
27
|
|
50
28
|
# Matches the ActiveJob API
|
51
29
|
def enqueued_at
|
52
|
-
seconds =
|
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
|
-
|
36
|
+
sidekiq_job_hash["args"] || []
|
59
37
|
end
|
60
38
|
end
|
61
39
|
end
|
@@ -1,11 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "observer"
|
4
|
-
|
5
3
|
module JobContracts
|
6
4
|
class Contract
|
7
|
-
include Observable
|
8
|
-
|
9
5
|
attr_reader :trigger, :queues
|
10
6
|
|
11
7
|
def initialize(trigger: :after, halt: false, queues: [], expected: {})
|
@@ -32,11 +28,9 @@ module JobContracts
|
|
32
28
|
# NOTE: subclasses should update `actual`, set `satisfied`, and call `super`
|
33
29
|
def enforce!(contractable)
|
34
30
|
return unless should_enforce?(contractable)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
ensure
|
39
|
-
delete_observer contractable
|
31
|
+
return if satisfied?
|
32
|
+
contractable.breached_contracts << self
|
33
|
+
invoke_contract_breach_callback contractable
|
40
34
|
end
|
41
35
|
|
42
36
|
def satisfied?
|
@@ -73,5 +67,11 @@ module JobContracts
|
|
73
67
|
protected
|
74
68
|
|
75
69
|
attr_accessor :satisfied
|
70
|
+
|
71
|
+
def invoke_contract_breach_callback(contractable)
|
72
|
+
callback = contractable.class.on_contract_breach_callback
|
73
|
+
callback = contractable.method(callback.to_sym) unless callback.is_a?(Proc)
|
74
|
+
callback.call self
|
75
|
+
end
|
76
76
|
end
|
77
77
|
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
|
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.
|
4
|
+
version: 0.1.4
|
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-
|
11
|
+
date: 2022-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -16,42 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 6.1.5
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 6.1.5
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: sidekiq
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 6.4.
|
33
|
+
version: 6.4.2
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 6.4.
|
40
|
+
version: 6.4.2
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: standard
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: magic_frozen_string_literal
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -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:
|