chaotic_job 0.0.1 โ 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.standard.yml +4 -0
- data/CHANGELOG.md +9 -0
- data/README.md +168 -6
- data/Rakefile +3 -1
- data/lib/chaotic_job/glitch.rb +1 -1
- data/lib/chaotic_job/performer.rb +64 -20
- data/lib/chaotic_job/scenario.rb +6 -1
- data/lib/chaotic_job/simulation.rb +8 -7
- data/lib/chaotic_job/version.rb +1 -1
- data/lib/chaotic_job.rb +34 -5
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d7a3e97903b960aad5ff163a8ea80d3d1c94d8427e86d0d06cb6c44ceffd7ad4
|
4
|
+
data.tar.gz: b4c2200a5436d1575f0f66d8647834514bd6563ac3fbf62a74014557d198ed90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa8f9e58bf1fa3eab4e4b6441e91824322e02043daea6fccb7f4d21844c739b34d376880ef03924fed43a7f7d49cf72fa536400698216ca58247cb287c49abd6
|
7
|
+
data.tar.gz: f8e83e868e13ed287f1ae9ff3b2560257b5c6fe1e6ba715bf400a93d2148c5a36d9372ac70aaadb5a498db198b3a0f0d9cd4bb3c00d138aa0ac4a8961c1e463a
|
data/.standard.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,4 +2,13 @@
|
|
2
2
|
|
3
3
|
## [0.1.0] - 2024-11-06
|
4
4
|
|
5
|
+
- Added `Journal` to log activity for tests
|
6
|
+
- Added `Performer` to correctly perform jobs with retries
|
7
|
+
- Added `Glitch` to inject transient failures into code execution
|
8
|
+
- Added `Scenario` to define a glitch for a specific job
|
9
|
+
- Added `Simulation` to run all possible error scenarios for a job
|
10
|
+
- Added `Helpers` module to provide easy to use methods for testing
|
11
|
+
|
12
|
+
## [0.0.1] - 2024-11-06
|
13
|
+
|
5
14
|
- Initial release
|
data/README.md
CHANGED
@@ -3,13 +3,16 @@
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/chaotic_job.svg)](https://rubygems.org/gems/chaotic_job)
|
4
4
|
[![Gem Downloads](https://img.shields.io/gem/dt/chaotic_job)](https://rubygems.org/gems/chaotic_job)
|
5
5
|
![Tests](https://github.com/fractaledmind/chaotic_job/actions/workflows/main.yml/badge.svg)
|
6
|
-
![Coverage](https://img.shields.io/badge/code%20coverage-
|
6
|
+
![Coverage](https://img.shields.io/badge/code%20coverage-92%25-success)
|
7
7
|
[![Sponsors](https://img.shields.io/github/sponsors/fractaledmind?color=eb4aaa&logo=GitHub%20Sponsors)](https://github.com/sponsors/fractaledmind)
|
8
8
|
[![Twitter Follow](https://img.shields.io/twitter/url?label=%40fractaledmind&style=social&url=https%3A%2F%2Ftwitter.com%2Ffractaledmind)](https://twitter.com/fractaledmind)
|
9
9
|
|
10
|
-
|
10
|
+
> [!TIP]
|
11
|
+
> This gem helps you test that your Active Jobs are reliable and resilient to failures. If you want to more easily *build* reliable and resilient Active Jobs, check out the companion [Acidic Job](https://github.com/fractaledmind/acidic_job/tree/alpha-1.0) gem.
|
12
|
+
|
13
|
+
`ChaoticJob` provides a set of tools to help you test the reliability and resilience of your Active Jobs. It does this by allowing you to simulate various types of failures and glitches that can occur in a production environment.
|
11
14
|
|
12
|
-
|
15
|
+
## Installation
|
13
16
|
|
14
17
|
Install the gem and add to the application's Gemfile by executing:
|
15
18
|
|
@@ -25,7 +28,166 @@ gem install chaotic_job
|
|
25
28
|
|
26
29
|
## Usage
|
27
30
|
|
28
|
-
|
31
|
+
`ChaoticJob` should be used primarily by including its helpers into your Active Job tests:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
class TestYourJob < ActiveJob::TestCase
|
35
|
+
include ChaoticJob::Helpers
|
36
|
+
|
37
|
+
test "job is reliable" do
|
38
|
+
# ...
|
39
|
+
end
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
The `ChaoticJob::Helpers` module provides 6 methods, 4 of which simply allow you to perform a job with retries in the proper way while the other 2 allow you to simulate failures and glitches.
|
44
|
+
|
45
|
+
### Performing Jobs
|
46
|
+
|
47
|
+
When testing job resilience, you will necessarily be testing how a job behaves when it retries. Unfortunately, the helpers provided by `ActiveJob::TestHelper` are tailored to testing the job's behavior on the first attempt.
|
48
|
+
|
49
|
+
Specifically, when you want to perform a job and all of its retries, you would naturally reach for the [`perform_enqueued_jobs`](https://api.rubyonrails.org/classes/ActiveJob/TestHelper.html#method-i-perform_enqueued_jobs) method.
|
50
|
+
|
51
|
+
> [!WARNING]
|
52
|
+
> Do not use `perform_enqueued_jobs` to test job retries.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
perform_enqueued_jobs do
|
56
|
+
Job.perform_later
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
But, this method does not behave as you would expect. Functionally, it overwrites the `enqueue` method to immediately perform the job, which means that instead of your job being performed in waves, the retry is performed _within_ the execution of the original job. This both confuses the logs and means the behavior in your tests are not representative of the behavior in production.
|
61
|
+
|
62
|
+
In order to properly test job retries, you should use the `perform_all` method provided by `ChaoticJob::Helpers`:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
Job.perform_later
|
66
|
+
perform_all
|
67
|
+
```
|
68
|
+
|
69
|
+
This helper will perform the job and all of its retries in the proper way, in waves, just like it would in production.
|
70
|
+
|
71
|
+
If you need more control over which batches of jobs are performed, you can use the `perform_all_before` and `perform_all_after` methods. These are particularly useful if you need to test the behavior of a job that schedules another job. You can use these methods to perform only the original job and its retries, assert the state of the system, and then perform the scheduled job and its retries.
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
JobThatSchedules.perform_later
|
75
|
+
perform_all_before(4.seconds)
|
76
|
+
assert_equal 1, enqueued_jobs.size
|
77
|
+
assert_equal 2, performed_jobs.size
|
78
|
+
|
79
|
+
perform_all_after(1.day)
|
80
|
+
assert_equal 0, enqueued_jobs.size
|
81
|
+
assert_equal 3, performed_jobs.size
|
82
|
+
```
|
83
|
+
|
84
|
+
You can pass either a `Time` object or an `ActiveSupport::Duration` object to these methods. And, to make the code as readable as possible, the `perform_all_before` is also aliased as the `perform_all_within` method. This allows you to write the example above as `perform_all_within(4.seconds)`.
|
85
|
+
|
86
|
+
### Simulating Failures
|
87
|
+
|
88
|
+
The helper methods for correctly performing jobs and their retries are useful, but they are not the primary reason for using `ChaoticJob`. The real power of this gem comes from its ability to simulate failures and glitches.
|
89
|
+
|
90
|
+
The first helper you can use is the `run_scenario` method. A scenario is simply a set of glitches that will be injected into the specified code once. Here is an example:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
test "scenario of a simple job" do
|
94
|
+
class Job < ActiveJob::Base
|
95
|
+
def perform
|
96
|
+
step_1
|
97
|
+
step_2
|
98
|
+
step_3
|
99
|
+
end
|
100
|
+
|
101
|
+
def step_1; ChaoticJob::Journal.log; end
|
102
|
+
def step_2; ChaoticJob::Journal.log; end
|
103
|
+
def step_3; ChaoticJob::Journal.log; end
|
104
|
+
end
|
105
|
+
|
106
|
+
run_scenario(Job.new, glitch: ["before", "#{__FILE__}:6"])
|
107
|
+
|
108
|
+
assert_equal 5, ChaoticJob::Journal.total
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
> [!NOTE]
|
113
|
+
> The `ChaoticJob::Journal` class is a simple class that you can use to log things happening. It is used here to track the behavior of the job. It's has a lean, but highly useful, interface:
|
114
|
+
> |method|description|
|
115
|
+
> |---|---|
|
116
|
+
> | `Journal.log` | log simply that something happened within the default scope |
|
117
|
+
> | `Journal.log(thing, scope: :special)` | log a particular value within a particular scope |
|
118
|
+
> | `Journal.total` | get the total number of logs under the default scope |
|
119
|
+
> | `Journal.total(scope: :special)` | get the total number of logs under a particular scope |
|
120
|
+
> | `Journal.all` | get all of the logged values under the default scope |
|
121
|
+
> | `Journal.all(scope: :special)` | get all of the logged values under a particular scope |
|
122
|
+
|
123
|
+
In this example, the job being tested is defined within the test case. You can, of course, also test jobs defined in your application. The key detail is the `glitch` keyword argument. A "glitch" is simply a tuple that describes precisely where you would like the failure to occur. The first element of the tuple is the location of the glitch, which can be either *before* or *after*. The second element is the location of the code that will be affected by the glitch, defined by its file path and line number. What this example scenario does is inject a glitch before the `step_3` method is called, here:
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
def perform
|
127
|
+
step_1
|
128
|
+
step_2
|
129
|
+
# <-- HERE
|
130
|
+
step_3
|
131
|
+
end
|
132
|
+
```
|
133
|
+
|
134
|
+
This glitch is a transient error, which are the only kind of errors that matter when testing resilience, as permanent errors mean your job will simply end up in the dead set. So, the glitch failure will occur once and only once, this forces a retry but does not prevent the job from completing.
|
135
|
+
|
136
|
+
If you want to simulate multiple glitches affecting a job run, you can use the plural `glitches` keyword argument instead and pass an array of tuples:
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
run_scenario(Job.new, glitches: [
|
140
|
+
["before", "#{__FILE__}:6"],
|
141
|
+
["before", "#{__FILE__}:7"]
|
142
|
+
])
|
143
|
+
```
|
144
|
+
|
145
|
+
Scenario testing is useful to test the behavior of a job under a specific set of conditions. But, if you want to test the behavior of a job under a variety of conditions, you can use the `run_simulation` method. Instead of running a single scenario, a simulation will run the full set of possible error scenarios for your job.
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
test "simulation of a simple job" do
|
149
|
+
class Job < ActiveJob::Base
|
150
|
+
def perform
|
151
|
+
step_1
|
152
|
+
step_2
|
153
|
+
step_3
|
154
|
+
end
|
155
|
+
|
156
|
+
def step_1 = ChaoticJob::Journal.log
|
157
|
+
def step_2 = ChaoticJob::Journal.log
|
158
|
+
def step_3 = ChaoticJob::Journal.log
|
159
|
+
end
|
160
|
+
|
161
|
+
run_simulation(Job.new) do |scenario|
|
162
|
+
assert_operator ChaoticJob::Journal.total, :>=, 3
|
163
|
+
end
|
164
|
+
end
|
165
|
+
```
|
166
|
+
|
167
|
+
In this example, the simulation will run 12 scenarios:
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
[
|
171
|
+
[[:after, "test_chaotic_job.rb:69"]],
|
172
|
+
[[:before, "test_chaotic_job.rb:75"]],
|
173
|
+
[[:after, "test_chaotic_job.rb:74"]],
|
174
|
+
[[:before, "test_chaotic_job.rb:74"]],
|
175
|
+
[[:after, "test_chaotic_job.rb:68"]],
|
176
|
+
[[:after, "test_chaotic_job.rb:70"]],
|
177
|
+
[[:before, "test_chaotic_job.rb:68"]],
|
178
|
+
[[:after, "test_chaotic_job.rb:73"]],
|
179
|
+
[[:after, "test_chaotic_job.rb:75"]],
|
180
|
+
[[:before, "test_chaotic_job.rb:69"]],
|
181
|
+
[[:before, "test_chaotic_job.rb:70"]],
|
182
|
+
[[:before, "test_chaotic_job.rb:73"]]
|
183
|
+
]
|
184
|
+
```
|
185
|
+
|
186
|
+
It generates all possible glitch scenarios by performing your job once with a [`TracePoint`](https://docs.ruby-lang.org/en/master/TracePoint.html) that captures each line executed in your job. It then computes all possible glitch locations to produce a set of scenarios that will be run.[^1] The block that you pass to `run_simulation` will be called for each scenario, allowing you to make assertions about the behavior of your job under all scenarios.
|
187
|
+
|
188
|
+
[^1]: The logic to determine all possible glitch locations essentially produces two locations, before and after, for each executed line. It then dedupes the functionally equivalent locations of `[:after, "file:1"]` and `[:before, "file:2"]`.
|
189
|
+
|
190
|
+
In your application tests, you will want to make assertions about the side-effects that your job performs, asserting that they are correctly idempotent (only occur once) and result in the correct state.
|
29
191
|
|
30
192
|
## Development
|
31
193
|
|
@@ -35,7 +197,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
35
197
|
|
36
198
|
## Contributing
|
37
199
|
|
38
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
200
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/fractaledmind/chaotic_job. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/fractaledmind/chaotic_job/blob/main/CODE_OF_CONDUCT.md).
|
39
201
|
|
40
202
|
## License
|
41
203
|
|
@@ -43,4 +205,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
43
205
|
|
44
206
|
## Code of Conduct
|
45
207
|
|
46
|
-
Everyone interacting in the ChaoticJob project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
208
|
+
Everyone interacting in the ChaoticJob project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/fractaledmind/chaotic_job/blob/main/CODE_OF_CONDUCT.md).
|
data/Rakefile
CHANGED
data/lib/chaotic_job/glitch.rb
CHANGED
@@ -61,7 +61,7 @@ module ChaoticJob
|
|
61
61
|
@breakpoints[path_with_line] ||= {}
|
62
62
|
# contents = File.read(file_path).split("\n") unless @file_contents.key?(path_with_line)
|
63
63
|
# @file_contents << contents
|
64
|
-
@breakpoints[path_with_line][position] = {
|
64
|
+
@breakpoints[path_with_line][position] = {block: block, executed: false}
|
65
65
|
end
|
66
66
|
|
67
67
|
def execute_block(handler)
|
@@ -1,40 +1,84 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
# Performer.new(Job1).perform_all_within(time)
|
5
|
-
# Performer.new(Job1).perform_all_after(time)
|
3
|
+
require "active_job"
|
6
4
|
|
7
5
|
module ChaoticJob
|
8
|
-
|
9
|
-
|
6
|
+
module Performer
|
7
|
+
extend ActiveJob::TestHelper
|
8
|
+
extend self
|
10
9
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
10
|
+
def perform_all
|
11
|
+
until (jobs = enqueued_jobs_where).empty?
|
12
|
+
perform(jobs)
|
13
|
+
end
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
def perform_all_before(cutoff)
|
17
|
+
time = resolve_cutoff(cutoff)
|
18
|
+
|
19
|
+
until (jobs = enqueued_jobs_where(before: time)).empty?
|
20
|
+
perform(jobs)
|
20
21
|
end
|
21
22
|
end
|
23
|
+
alias_method :perform_all_within, :perform_all_before
|
24
|
+
|
25
|
+
def perform_all_after(cutoff)
|
26
|
+
time = resolve_cutoff(cutoff)
|
22
27
|
|
23
|
-
|
28
|
+
until (jobs = enqueued_jobs_where(after: time)).empty?
|
29
|
+
perform(jobs)
|
30
|
+
end
|
24
31
|
end
|
25
32
|
|
26
|
-
def
|
33
|
+
def perform(jobs)
|
34
|
+
jobs.each do |payload|
|
35
|
+
queue_adapter.enqueued_jobs.delete(payload)
|
36
|
+
queue_adapter.performed_jobs << payload
|
37
|
+
instantiate_job(payload, skip_deserialize_arguments: true).perform_now
|
38
|
+
end.count
|
27
39
|
end
|
28
40
|
|
29
|
-
|
41
|
+
def enqueued_jobs_where(before: nil, after: nil)
|
42
|
+
enqueued_jobs
|
43
|
+
.sort_by { |job| job["scheduled_at"] }
|
44
|
+
.select do |job|
|
45
|
+
scheduled_at = job[:at]
|
30
46
|
|
31
|
-
|
32
|
-
|
33
|
-
|
47
|
+
next true if scheduled_at.nil?
|
48
|
+
|
49
|
+
# Skip if the job is scheduled after the cutoff time
|
50
|
+
if before
|
51
|
+
next false if scheduled_at > before.to_f
|
52
|
+
end
|
53
|
+
|
54
|
+
# Skip if the job is scheduled before the cutoff time
|
55
|
+
if after
|
56
|
+
next false if scheduled_at < after.to_f
|
57
|
+
end
|
58
|
+
|
59
|
+
true
|
60
|
+
end
|
34
61
|
end
|
35
62
|
|
36
|
-
def
|
37
|
-
|
63
|
+
def resolve_cutoff(cutoff)
|
64
|
+
time = case cutoff
|
65
|
+
in ActiveSupport::Duration
|
66
|
+
cutoff.from_now
|
67
|
+
in Time
|
68
|
+
cutoff
|
69
|
+
end
|
70
|
+
delta = (Time.now - time).abs
|
71
|
+
changeset = case delta
|
72
|
+
when 0..59 # seconds
|
73
|
+
{usec: 0}
|
74
|
+
when 60..3599 # minutes
|
75
|
+
{sec: 0, usec: 0}
|
76
|
+
when 3600..86_399 # hours
|
77
|
+
{min: 0, sec: 0, usec: 0}
|
78
|
+
when 86_400..Float::INFINITY # days+
|
79
|
+
{hour: 0, min: 0, sec: 0, usec: 0}
|
80
|
+
end
|
81
|
+
time.change(**changeset)
|
38
82
|
end
|
39
83
|
end
|
40
84
|
end
|
data/lib/chaotic_job/scenario.rb
CHANGED
@@ -21,7 +21,12 @@ module ChaoticJob
|
|
21
21
|
|
22
22
|
ActiveSupport::Notifications.subscribed(->(event) { @events << event.dup }, @capture) do
|
23
23
|
glitch.inject! do
|
24
|
-
block_given?
|
24
|
+
if block_given?
|
25
|
+
yield
|
26
|
+
else
|
27
|
+
@job.enqueue
|
28
|
+
Performer.perform_all
|
29
|
+
end
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
@@ -6,22 +6,23 @@
|
|
6
6
|
# Simulation.new(job).scenarios
|
7
7
|
module ChaoticJob
|
8
8
|
class Simulation
|
9
|
-
def initialize(job,
|
9
|
+
def initialize(job, depth: 1, variations: 100, test: nil, seed: nil)
|
10
10
|
@template = job
|
11
|
-
@
|
11
|
+
@depth = depth
|
12
12
|
@variations = variations
|
13
|
+
@test = test
|
13
14
|
@seed = seed || Random.new_seed
|
14
15
|
@random = Random.new(@seed)
|
15
|
-
@depth = depth
|
16
16
|
end
|
17
17
|
|
18
18
|
def run(&callback)
|
19
19
|
@template.class.retry_on RetryableError, attempts: @depth + 2, wait: 1, jitter: 0
|
20
20
|
|
21
|
-
debug "Running #{variants.size} simulations of the total #{permutations.size} possibilities..."
|
21
|
+
debug "๐พ Running #{variants.size} simulations of the total #{permutations.size} possibilities..."
|
22
22
|
|
23
23
|
scenarios.map do |scenario|
|
24
24
|
run_scenario(scenario, &callback)
|
25
|
+
print "ยท"
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
@@ -70,7 +71,7 @@ module ChaoticJob
|
|
70
71
|
trace = TracePoint.new(:line) do |tp|
|
71
72
|
next if tp.defined_class == self.class
|
72
73
|
next unless tp.path == job_file_path ||
|
73
|
-
|
74
|
+
tp.defined_class == job_class
|
74
75
|
|
75
76
|
@callstack << [tp.path, tp.lineno]
|
76
77
|
end
|
@@ -81,9 +82,9 @@ module ChaoticJob
|
|
81
82
|
end
|
82
83
|
|
83
84
|
def run_scenario(scenario, &callback)
|
84
|
-
debug "Running simulation with scenario: #{scenario}"
|
85
|
+
debug "๐พ Running simulation with scenario: #{scenario}"
|
85
86
|
@test.before_setup
|
86
|
-
scenario.
|
87
|
+
scenario.run
|
87
88
|
@test.after_teardown
|
88
89
|
callback.call(scenario)
|
89
90
|
end
|
data/lib/chaotic_job/version.rb
CHANGED
data/lib/chaotic_job.rb
CHANGED
@@ -1,17 +1,46 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "chaotic_job/version"
|
4
|
+
require_relative "chaotic_job/journal"
|
5
|
+
require_relative "chaotic_job/performer"
|
6
|
+
require_relative "chaotic_job/glitch"
|
7
|
+
require_relative "chaotic_job/scenario"
|
8
|
+
require_relative "chaotic_job/simulation"
|
4
9
|
|
5
10
|
module ChaoticJob
|
6
|
-
class RetryableError < StandardError
|
11
|
+
class RetryableError < StandardError
|
12
|
+
end
|
7
13
|
|
8
14
|
module Helpers
|
9
|
-
def
|
10
|
-
|
15
|
+
def perform_all
|
16
|
+
Performer.perform_all
|
17
|
+
end
|
18
|
+
|
19
|
+
def perform_all_within(time)
|
20
|
+
Performer.perform_all_within(time)
|
21
|
+
end
|
22
|
+
|
23
|
+
def perform_all_before(time)
|
24
|
+
Performer.perform_all_before(time)
|
25
|
+
end
|
26
|
+
|
27
|
+
def perform_all_after(time)
|
28
|
+
Performer.perform_all_after(time)
|
29
|
+
end
|
30
|
+
|
31
|
+
def run_simulation(job, depth: nil, variations: nil, &block)
|
32
|
+
seed = defined?(RSpec) ? RSpec.configuration.seed : Minitest.seed
|
33
|
+
kwargs = {test: self, seed: seed}
|
34
|
+
kwargs[:depth] = depth if depth
|
35
|
+
kwargs[:variations] = variations if variations
|
36
|
+
Simulation.new(job, **kwargs).run(&block)
|
11
37
|
end
|
12
38
|
|
13
|
-
def run_scenario(job)
|
14
|
-
|
39
|
+
def run_scenario(job, glitch: nil, glitches: nil, raise: nil, capture: nil)
|
40
|
+
kwargs = {glitches: glitches || [glitch]}
|
41
|
+
kwargs[:raise] = raise if raise
|
42
|
+
kwargs[:capture] = capture if capture
|
43
|
+
Scenario.new(job, **kwargs).run
|
15
44
|
end
|
16
45
|
end
|
17
46
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chaotic_job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen Margheim
|
@@ -9,7 +9,21 @@ autorequire:
|
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
11
|
date: 2024-11-07 00:00:00.000000000 Z
|
12
|
-
dependencies:
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activejob
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '7.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '7.0'
|
13
27
|
description:
|
14
28
|
email:
|
15
29
|
- stephen.margheim@gmail.com
|