standard_procedure_operations 0.7.0 → 0.7.2

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: d5804e91c48ca11b9306c1d8d2c3006df7916dcd3e768629cf492b1daa409725
4
- data.tar.gz: 2c0f4a513bb1bd685f44daf46f28e7ecb2ac0909a703ae79240ff0587fc74d1c
3
+ metadata.gz: 462512e945573c5809f480e318e03c17a15604e8f8362934d2c730f2827f54a5
4
+ data.tar.gz: 3446e47c75e17db5384b8ba8a86a5740fbd095ea6a3f57ae6eb9d05dbac50e1c
5
5
  SHA512:
6
- metadata.gz: 1f8335c58e7df31046d08ab67cf99d7bf1cd0a1a52aa24433b79932f418c9d0de945d702d7039eabb6e66ed4a94484a2aa3d9bdb415d60859b9007feff9c64e2
7
- data.tar.gz: 8cb8aa2940d5b4658582c14aef3db7d715c3c6af2f66b1bd838514ad11e67a6edbc8a9b95eb9cd8e57fc8293156365acaf95e017d8d13572fe5d1259c2b27269
6
+ metadata.gz: 442ba282285358dc7baa1bbd9f00a4fa2aaa76ee4009a0638073f95e6e099c993d7eb0b9381884b781432874bd542a2a8fde4a6c150bd7c3fdf5028f94ac6951
7
+ data.tar.gz: 6458262e8f3efd03256c1a4e6efe7be32d925ce88852afc93869d28b6ed7e77e6fb0108020ea1c39ab15ca79feaaa5eb2d45e129ce0829064c1b779d727e39eb
data/README.md CHANGED
@@ -9,7 +9,7 @@ In effect, that flowchart is a state machine - with "decision states" and "actio
9
9
 
10
10
  ## Breaking Change
11
11
 
12
- Version 0.7.0 includes breaking changes. There are migrations which rename your existing `operations_tasks` and `operations_task_participants` tables (so the data is not deleted), then a new `operations_tasks` table is created with a simplified structure.
12
+ Version 0.7.0 includes breaking changes. When you run `bin/rails operations:migrations:install` one of the migrations will drop your existing `operations_tasks` and `operations_task_participants` tables. If you need the historic data in those tables, then edit the migration to rename the tables instead. Also you will need to update your tests to use the new `test` method.
13
13
 
14
14
  ## Usage
15
15
 
@@ -193,7 +193,7 @@ end
193
193
  ```
194
194
  #### Wait handlers
195
195
 
196
- The registration process performs an action, `send_invitation` and then waits until a `name_provided?`. A `wait handler` is similar to a `decision handler` but if the conditions are not met, instead of raising an error, the task goes to sleep. A background process (see bwlow) wakes the task periodically to reevaluate the condition. Or, an `interaction` can be triggered; this is similar to an action because it does something, but it also immediately reevaluates the current wait handler. So in this case, when the `register!` interaction completes, the `name_provided?` wait handler is reevaluated and, because the `name` has now been supplied, it can move on to the `create_user` state.
196
+ The registration process performs an action, `send_invitation` and then waits until a `name_provided?`. A `wait handler` is similar to a `decision handler` but if the conditions are not met, instead of raising an error, the task goes to sleep. A background process (see below) wakes the task periodically to reevaluate the condition. Or, an `interaction` can be triggered; this is similar to an action because it does something, but it also immediately reevaluates the current wait handler. So in this case, when the `register!` interaction completes, the `name_provided?` wait handler is reevaluated and, because the `name` has now been supplied, it can move on to the `create_user` state.
197
197
 
198
198
  When a task reaches a wait handler, it goes to sleep and expects to be woken up at some point in the future. You can specify how often it is woken up by adding a `delay 10.minutes` declaration to your class. The default is `1.minute`. Likewise, if a task does not change state after a certain period it fails with an `Operations::Timeout` exception. You can set this timeout by declaring `timeout 48.hours` (the default is `24.hours`).
199
199
 
@@ -280,7 +280,30 @@ However, it also means that your database table could fill up with junk that you
280
280
 
281
281
  ## Testing
282
282
 
283
- TBD
283
+ Because the flow for a task may be complex, it's best to test each state in isolation. To help with this, there is a `test` method on the `Operations::Task` class, which creates a task, in your desired state, then runs the appropriate handler. Then you can check that it has done what you expect.
284
+
285
+ ```ruby
286
+ class WeekendChecker < Operations::Task
287
+ has_attribute :day_of_week, :string, default: "Monday"
288
+ validates :day_of_week, presence: true
289
+ starts_with :is_it_the_weekend?
290
+
291
+ decision :is_it_the_weekend? do
292
+ condition { %w[Saturday Sunday].include? day_of_week }
293
+ if_true :weekend
294
+ if_false :weekday
295
+ end
296
+
297
+ result :weekend
298
+ result :weekday
299
+ end
300
+
301
+ task = WeekendChecker.verify :is_it_the_weekend?, day_of_week: "Saturday"
302
+ expect(task).to be_in :weekend
303
+
304
+ task = WeekendChecker.verify :is_it_the_weekend?, day_of_week: "Wednesday"
305
+ expect(task).to be_in :weekday
306
+ ```
284
307
 
285
308
  ## Installation
286
309
  Step 1: Add the gem to your Rails application's Gemfile:
@@ -327,4 +350,4 @@ The gem is available as open source under the terms of the [LGPL License](/LICEN
327
350
  - [x] Add visualization export for task flows
328
351
  - [ ] Replace ActiveJob with a background process
329
352
  - [ ] Rename StateManagent with Plan
330
- - [ ] Add interactions
353
+ - [ ] Add interactions
@@ -0,0 +1,11 @@
1
+ module Operations::Task::Testing
2
+ extend ActiveSupport::Concern
3
+
4
+ class_methods do
5
+ def test state, **attributes
6
+ create!(current_state: state, **attributes).tap do |task|
7
+ task.call_handler
8
+ end
9
+ end
10
+ end
11
+ end
@@ -3,6 +3,8 @@ module Operations
3
3
  include HasAttributes
4
4
  include Plan
5
5
  include Index
6
+ include Testing
7
+
6
8
  scope :ready_to_wake, -> { ready_to_wake_at(Time.current) }
7
9
  scope :ready_to_wake_at, ->(time) { where(wakes_at: ..time) }
8
10
  scope :expired, -> { expires_at(Time.current) }
@@ -24,9 +26,11 @@ module Operations
24
26
  has_attribute :exception_backtrace, :string
25
27
 
26
28
  def call(immediate: false)
27
- while active?
29
+ state = ""
30
+ while active? && (state != current_state)
31
+ state = current_state
28
32
  Rails.logger.debug { "--- #{self}: #{current_state}" }
29
- (handler_for(current_state).immediate? || immediate) ? handler_for(current_state).call(self) : go_to_sleep!
33
+ (handler_for(current_state).immediate? || immediate) ? call_handler : go_to_sleep!
30
34
  end
31
35
  rescue => ex
32
36
  record_error! ex
@@ -41,6 +45,8 @@ module Operations
41
45
 
42
46
  def record_error!(exception) = update!(task_status: "failed", exception_class: exception.class.to_s, exception_message: exception.message.to_s, exception_backtrace: exception.backtrace)
43
47
 
48
+ def call_handler = handler_for(current_state).call(self)
49
+
44
50
  private def go_to_sleep! = update!(default_times.merge(task_status: "waiting"))
45
51
 
46
52
  private def activate_and_call
@@ -1,3 +1,3 @@
1
1
  module Operations
2
- VERSION = "0.7.0"
2
+ VERSION = "0.7.2"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: standard_procedure_operations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rahoul Baruah
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-07-02 00:00:00.000000000 Z
10
+ date: 2025-07-10 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rails
@@ -60,6 +60,7 @@ files:
60
60
  - app/models/operations/task/plan/result_handler.rb
61
61
  - app/models/operations/task/plan/wait_handler.rb
62
62
  - app/models/operations/task/runner.rb
63
+ - app/models/operations/task/testing.rb
63
64
  - app/models/operations/task_participant.rb
64
65
  - config/routes.rb
65
66
  - db/migrate/20250701190516_rename_existing_operations_tables.rb