stepper_motor 0.1.3 → 0.1.5
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/.standard.yml +2 -6
- data/CHANGELOG.md +2 -2
- data/Rakefile +6 -3
- data/lib/stepper_motor/cyclic_scheduler.rb +2 -0
- data/lib/stepper_motor/forward_scheduler.rb +5 -1
- data/lib/stepper_motor/perform_step_job.rb +2 -0
- data/lib/stepper_motor/perform_step_job_v2.rb +12 -0
- data/lib/stepper_motor/reap_hung_journeys_job.rb +2 -0
- data/lib/stepper_motor/step.rb +2 -0
- data/lib/stepper_motor/test_helper.rb +2 -0
- data/lib/stepper_motor/version.rb +1 -1
- data/lib/stepper_motor.rb +1 -0
- data/spec/helpers/side_effects.rb +2 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/stepper_motor/cyclic_scheduler_spec.rb +5 -5
- data/spec/stepper_motor/forward_scheduler_spec.rb +41 -0
- data/spec/stepper_motor/generator_spec.rb +2 -0
- data/spec/stepper_motor/journey_spec.rb +3 -3
- data/spec/stepper_motor/test_helper_spec.rb +2 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7846dbc38d7f5d10b018f8e052e33f2347598e59bcf04dfcc4b49c3bcd247fd6
|
4
|
+
data.tar.gz: 947b3810bff07dd61b72c86319d83f1ef93341986541a8b8ff9bfd8fe0230461
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eab053515d0672cdd23065e0c7c13276cd6c972d07df6340755052cc8412e447d5d37ad31a34fac9c0ddb587c73b050a0571bab7a521544963c2a2149f1c069d
|
7
|
+
data.tar.gz: d4041d89eb0cb2abf39721ff426ea99f33548576cd510fd8cbf5b5723f1f920075dbda0b692323afc89715eb266957d0d21907219c0a06aab7848237d1db1ddf
|
data/.standard.yml
CHANGED
@@ -1,8 +1,4 @@
|
|
1
1
|
ruby_version: 3.1
|
2
2
|
ignore:
|
3
|
-
- 'spec/**/*':
|
4
|
-
-
|
5
|
-
- Style/GlobalVars
|
6
|
-
- 'lib/zip_kit/rack_body.rb': # Erroneous detection
|
7
|
-
- Lint/OrderedMagicComments
|
8
|
-
- Layout/EmptyLineAfterMagicComment
|
3
|
+
- 'spec/app/db/**/*':
|
4
|
+
- Layout/TrailingWhitespace # Templated migrations have whitespace
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
## [0.1.
|
1
|
+
## [0.1.x] - 2025-01-01
|
2
2
|
|
3
|
-
-
|
3
|
+
- Development versions. Expect bugs of mysterious kinds.
|
data/Rakefile
CHANGED
@@ -2,9 +2,12 @@
|
|
2
2
|
|
3
3
|
require "bundler/gem_tasks"
|
4
4
|
require "rspec/core/rake_task"
|
5
|
-
|
6
|
-
RSpec::Core::RakeTask.new(:spec)
|
7
|
-
|
8
5
|
require "standard/rake"
|
9
6
|
|
7
|
+
task :format do
|
8
|
+
`bundle exec standardrb --fix`
|
9
|
+
`bundle exec magic_frozen_string_literal .`
|
10
|
+
end
|
11
|
+
|
12
|
+
RSpec::Core::RakeTask.new(:spec)
|
10
13
|
task default: %i[spec standard]
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# The cyclic scheduler is designed to be run regularly via a cron job. On every
|
2
4
|
# cycle, it is going to look for Journeys which are going to come up for step execution
|
3
5
|
# before the next cycle is supposed to run. Then it is going to enqueue jobs to perform
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# The forward scheduler enqueues a job for every Journey that
|
2
4
|
# gets sent to the `#schedule`. The job is then stored in the queue
|
3
5
|
# and gets picked up by the ActiveJob worker normally. This is the simplest
|
@@ -13,6 +15,8 @@
|
|
13
15
|
# this scheduler is not a good fit for you, and you will need to use the {CyclicScheduler} instead.
|
14
16
|
class StepperMotor::ForwardScheduler
|
15
17
|
def schedule(journey)
|
16
|
-
StepperMotor::
|
18
|
+
StepperMotor::PerformStepJobV2
|
19
|
+
.set(wait_until: journey.next_step_to_be_performed_at)
|
20
|
+
.perform_later(journey_id: journey.id, journey_class_name: journey.class.to_s)
|
17
21
|
end
|
18
22
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_job"
|
4
|
+
|
5
|
+
class StepperMotor::PerformStepJobV2 < ActiveJob::Base
|
6
|
+
def perform(journey_id:, journey_class_name:, **)
|
7
|
+
journey = StepperMotor::Journey.find(journey_id)
|
8
|
+
journey.perform_next_step!
|
9
|
+
rescue ActiveRecord::RecordNotFound
|
10
|
+
# The journey has been canceled and destroyed previously or elsewhere
|
11
|
+
end
|
12
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# The purpose of this job is to find journeys which have, for whatever reason, remained in the
|
2
4
|
# `performing` state for far longer than the journey is supposed to. At the moment it assumes
|
3
5
|
# any journey that stayed in `performing` for longer than 1 hour has hung. Add this job to your
|
data/lib/stepper_motor/step.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Describes a step in a journey. These objects get stored inside the `step_definitions`
|
2
4
|
# array of the Journey subclass. When the step gets performed, the block passed to the
|
3
5
|
# constructor will be instance_exec'd with the Journey model being the context
|
data/lib/stepper_motor.rb
CHANGED
@@ -13,6 +13,7 @@ module StepperMotor
|
|
13
13
|
autoload :Journey, File.dirname(__FILE__) + "/stepper_motor/journey.rb"
|
14
14
|
autoload :Step, File.dirname(__FILE__) + "/stepper_motor/step.rb"
|
15
15
|
autoload :PerformStepJob, File.dirname(__FILE__) + "/stepper_motor/perform_step_job.rb"
|
16
|
+
autoload :PerformStepJobV2, File.dirname(__FILE__) + "/stepper_motor/perform_step_job_v2.rb"
|
16
17
|
autoload :InstallGenerator, File.dirname(__FILE__) + "/generators/install_generator.rb"
|
17
18
|
autoload :ForwardScheduler, File.dirname(__FILE__) + "/stepper_motor/forward_scheduler.rb"
|
18
19
|
autoload :CyclicScheduler, File.dirname(__FILE__) + "/stepper_motor/cyclic_scheduler.rb"
|
data/spec/spec_helper.rb
CHANGED
@@ -40,7 +40,7 @@ end
|
|
40
40
|
|
41
41
|
module ActiveSupportTestCaseMethodsStub
|
42
42
|
def self.included(into)
|
43
|
-
into.before(:each) { before_setup }
|
43
|
+
into.before(:each) { before_setup }
|
44
44
|
into.after(:each) { after_teardown }
|
45
45
|
end
|
46
46
|
|
@@ -85,5 +85,6 @@ RSpec.configure do |config|
|
|
85
85
|
StepperMotorRailtieTestHelpers.establish_test_connection
|
86
86
|
StepperMotorRailtieTestHelpers.run_generator
|
87
87
|
StepperMotorRailtieTestHelpers.run_migrations
|
88
|
+
ActiveJob::Base.logger.level = Logger::FATAL
|
88
89
|
end
|
89
90
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative "../spec_helper"
|
2
4
|
|
3
5
|
RSpec.describe "StepperMotor::CyclicScheduler" do
|
@@ -13,11 +15,9 @@ RSpec.describe "StepperMotor::CyclicScheduler" do
|
|
13
15
|
end
|
14
16
|
|
15
17
|
def far_future_journey_class
|
16
|
-
@klass ||=
|
17
|
-
|
18
|
-
|
19
|
-
raise "We do not test this so it should never run"
|
20
|
-
end
|
18
|
+
@klass ||= create_journey_subclass do
|
19
|
+
step :do_thing, wait: 40.minutes do
|
20
|
+
raise "We do not test this so it should never run"
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe "StepperMotor::ForwardScheduler" do
|
6
|
+
include ActiveJob::TestHelper
|
7
|
+
|
8
|
+
before do
|
9
|
+
@previous_scheduler = StepperMotor.scheduler
|
10
|
+
StepperMotor::Journey.delete_all
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
StepperMotor.scheduler = @previous_scheduler
|
15
|
+
end
|
16
|
+
|
17
|
+
def far_future_journey_class
|
18
|
+
@klass ||= create_journey_subclass do
|
19
|
+
step :do_thing, wait: 40.minutes do
|
20
|
+
raise "We do not test this so it should never run"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "schedules a journey 40 minutes ahead" do
|
26
|
+
scheduler = StepperMotor::ForwardScheduler.new
|
27
|
+
StepperMotor.scheduler = scheduler
|
28
|
+
|
29
|
+
expect(scheduler).to receive(:schedule).with(instance_of(far_future_journey_class)).once.and_call_original
|
30
|
+
_journey = far_future_journey_class.create!
|
31
|
+
|
32
|
+
expect(enqueued_jobs.size).to eq(1)
|
33
|
+
job = enqueued_jobs.first
|
34
|
+
|
35
|
+
expect(job["job_class"]).to eq("StepperMotor::PerformStepJobV2")
|
36
|
+
expect(job["scheduled_at"]).not_to be_nil
|
37
|
+
|
38
|
+
scheduled_at = Time.parse(job["scheduled_at"])
|
39
|
+
expect(scheduled_at).to be_within(5.seconds).of(40.minutes.from_now)
|
40
|
+
end
|
41
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative "../spec_helper"
|
2
4
|
|
3
5
|
# rubocop:disable Lint/ConstantDefinitionInBlock
|
@@ -26,8 +28,6 @@ RSpec.describe "StepperMotor::Journey" do
|
|
26
28
|
end
|
27
29
|
|
28
30
|
it "allows a journey consisting of multiple named steps to be defined and performed to completion" do
|
29
|
-
step_names = [:step1, :step2, :step3]
|
30
|
-
|
31
31
|
multi_step_journey_class = create_journey_subclass do
|
32
32
|
[:step1, :step2, :step3].each do |step_name|
|
33
33
|
step step_name do
|
@@ -103,7 +103,7 @@ RSpec.describe "StepperMotor::Journey" do
|
|
103
103
|
end
|
104
104
|
|
105
105
|
it "allows a journey where steps are delayed in time using wait:" do
|
106
|
-
timely_journey_class =
|
106
|
+
timely_journey_class = create_journey_subclass do
|
107
107
|
step wait: 10.hours do
|
108
108
|
SideEffects.touch! "after_10_hours.txt"
|
109
109
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stepper_motor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -136,6 +136,20 @@ dependencies:
|
|
136
136
|
- - '='
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: 1.28.5
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: magic_frozen_string_literal
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
154
|
name: yard
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -188,6 +202,7 @@ files:
|
|
188
202
|
- lib/stepper_motor/forward_scheduler.rb
|
189
203
|
- lib/stepper_motor/journey.rb
|
190
204
|
- lib/stepper_motor/perform_step_job.rb
|
205
|
+
- lib/stepper_motor/perform_step_job_v2.rb
|
191
206
|
- lib/stepper_motor/railtie.rb
|
192
207
|
- lib/stepper_motor/reap_hung_journeys_job.rb
|
193
208
|
- lib/stepper_motor/step.rb
|
@@ -197,6 +212,7 @@ files:
|
|
197
212
|
- spec/helpers/side_effects.rb
|
198
213
|
- spec/spec_helper.rb
|
199
214
|
- spec/stepper_motor/cyclic_scheduler_spec.rb
|
215
|
+
- spec/stepper_motor/forward_scheduler_spec.rb
|
200
216
|
- spec/stepper_motor/generator_spec.rb
|
201
217
|
- spec/stepper_motor/journey_spec.rb
|
202
218
|
- spec/stepper_motor/test_helper_spec.rb
|