lite-command 3.1.5 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 25949bea3778fbe660ae361819879bc36deb461fb37e9efa4ad11012529ae682
4
- data.tar.gz: 7f9df66b9027c3c7e3cb7b8efaad1508dec68c22b4b63ab27c4ffd123707519e
3
+ metadata.gz: ecfaebe941a3ed585e42a5a43b361d60de38076b6a4254125722b13d57294885
4
+ data.tar.gz: da15660c9410a9c8797d6c322ab79797f800f5233319a7a39d6476bba10504ec
5
5
  SHA512:
6
- metadata.gz: 9c2ee67da223708a63852d539ab82f7a893214c1016376fc0af4496d224ccdcfef3340b1267f6fec11348ae8d2ede2c87b605494aa2090a8f449c317a3d9613a
7
- data.tar.gz: 29ec28857fc0e8f29e1ba34a41cae8b44298a44c9477e73a237f5eb708965ba555a4b82edff984b20b61b4f1967ce93586ec74075a8421f6481c353865c0e275
6
+ metadata.gz: b91f356964b41577a7e274a5cc5cf46c74b60a088ffa781e7c5f3cbf0f7bd7713accf16ddf8bee16e99342e04a0040ea8dab2fb8c5ff7eb3132d7e3000596ca0
7
+ data.tar.gz: d905466a1fe16049f5af3877c2488120eb581070fe85a9bf20654cf09127bcccc8e6e9a79c436f16164e3104d5fc7d1bd6bbb7b839069250d29cc4b551e8c47e
data/CHANGELOG.md CHANGED
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [3.2.0] - 2024-10-29
10
+ ### Changed
11
+ - Move callbacks to hooks instead of try methods
12
+
9
13
  ## [3.1.5] - 2024-10-28
10
14
  ### Changed
11
15
  - Renamed private `delegate` method to `delegates` to prevent rails clash
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- lite-command (3.1.5)
4
+ lite-command (3.2.0)
5
5
  activemodel
6
6
  ostruct
7
7
 
data/README.md CHANGED
@@ -33,10 +33,9 @@ Or install it yourself as:
33
33
  * [States](#states)
34
34
  * [Statuses](#statuses)
35
35
  * [Hooks](#hooks)
36
- * [State Hooks](#status-hooks)
37
- * [Attribute Hooks](#attribute-hooks)
38
- * [Execution Hooks](#execution-hooks)
36
+ * [Lifecycle Hooks](#lifecycle-hooks)
39
37
  * [Status Hooks](#status-hooks)
38
+ * [State Hooks](#state-hooks)
40
39
  * [Children](#children)
41
40
  * [Throwing Faults](#throwing-faults)
42
41
  * [Sequences](#sequences)
@@ -143,6 +142,10 @@ cmd.raise!(original: true) #=> raises Lite::Command::Fault
143
142
  # On exception:
144
143
  cmd.raise!(original: false) #=> raises Lite::Command::Error
145
144
  cmd.raise!(original: true) #=> raises StandardError
145
+
146
+ # Access the exception objects directly
147
+ cmd.original_exception #=> <StandardError ...>
148
+ cmd.command_exception #=> <Lite::Command::Error ...>
146
149
  ```
147
150
 
148
151
  ### Dynamic Faults
@@ -361,9 +364,6 @@ cmd.status #=> "invalid"
361
364
  cmd.reason #=> "Invalid message start value"
362
365
  cmd.metadata #=> { i18n: "gb.invalid_start_value" }
363
366
 
364
- cmd.original_exception #=> <RuntimeError ...>
365
- cmd.command_exception #=> <DecryptSecretMessage::Error ...>
366
-
367
367
  cmd.success? #=> false
368
368
  cmd.noop? #=> false
369
369
  cmd.invalid? #=> true
@@ -387,140 +387,91 @@ cmd.bad?("Other reason") #=> false
387
387
  ## Hooks
388
388
 
389
389
  Use hooks to run arbituary code at transition points and on finalized internals.
390
- The following is an example of the hooks called for a failed command with a
391
- successful child command.
390
+ All hooks are ran in the order they are defined. Hooks types can be defined
391
+ multiple times. The following is an example of the hooks called for a failed
392
+ command with a successful child command.
392
393
 
393
394
  ```ruby
394
- -> 1. FooCommand.on_pending
395
- -> 2. FooCommand.on_before_execution
396
- -> 3. FooCommand.on_executing
397
- ---> 3a. BarCommand.on_pending
398
- ---> 3b. BarCommand.on_before_execution
399
- ---> 3c. BarCommand.on_executing
400
- ---> 3d. BarCommand.on_after_execution
401
- ---> 3e. BarCommand.on_success
402
- ---> 3f. BarCommand.on_complete
403
- -> 4. FooCommand.on_after_execution
404
- -> 5. FooCommand.on_failure
405
- -> 6. FooCommand.on_interrupted
395
+ -> 1. FooCommand.after_initialize
396
+ -> 2. FooCommand.on_pending
397
+ -> 3. FooCommand.before_validation
398
+ -> 4. FooCommand.after_validation
399
+ -> 5. FooCommand.before_execution
400
+ -> 6. FooCommand.on_executing
401
+ ---> 6a. BarCommand.after_initialize
402
+ ---> 6b. BarCommand.on_pending
403
+ ---> 6c. BarCommand.before_validation
404
+ ---> 6d. BarCommand.after_validation
405
+ ---> 6e. BarCommand.before_execution
406
+ ---> 6f. BarCommand.on_executing
407
+ ---> 6g. BarCommand.after_execution
408
+ ---> 6h. BarCommand.on_failure
409
+ ---> 6i. BarCommand.on_interrupted
410
+ -> 7. FooCommand.after_execution
411
+ -> 8. FooCommand.on_failure
412
+ -> 9. FooCommand.on_interrupted
406
413
  ```
407
414
 
408
- ### Status Hooks
415
+ ### Lifecycle Hooks
409
416
 
410
- Define one or more callbacks that are called during transitions between states.
417
+ Define before and after callbacks to call around execution.
411
418
 
412
419
  ```ruby
413
420
  class DecryptSecretMessage < Lite::Command::Base
414
421
 
415
- def call
416
- # ...
417
- end
418
-
419
- private
420
-
421
- def on_pending
422
- # eg: Append additional contextual data
423
- end
424
-
425
- def on_executing
426
- # eg: Insert inspection debugger
427
- end
428
-
429
- def on_complete
430
- # eg: Log message for posterity
431
- end
432
-
433
- def on_interrupted
434
- # eg: Report to APM with tags and metadata
435
- end
436
-
437
- end
438
- ```
439
-
440
- ### Attribute Hooks
441
-
442
- Define before attribtue validation callbacks.
443
-
444
- ```ruby
445
- class DecryptSecretMessage < Lite::Command::Base
422
+ after_initialize :some_method
423
+ before_validation :some_method
424
+ after_validation :some_method
425
+ before_execution :some_method
426
+ after_execution :some_method
446
427
 
447
428
  def call
448
429
  # ...
449
430
  end
450
431
 
451
- private
452
-
453
- def on_before_validation
454
- # eg: Normalize context data
455
- end
456
-
457
432
  end
458
433
  ```
459
434
 
460
- ### Execution Hooks
435
+ ### Status Hooks
461
436
 
462
- Define before and after callbacks to call around execution.
437
+ Define one or more callbacks that are called after execution for
438
+ specific statuses.
463
439
 
464
440
  ```ruby
465
441
  class DecryptSecretMessage < Lite::Command::Base
466
442
 
443
+ on_success :some_method
444
+ on_noop :some_method
445
+ on_invalid :some_method
446
+ on_failure :some_method
447
+ on_error :some_method
448
+
467
449
  def call
468
450
  # ...
469
451
  end
470
452
 
471
- private
472
-
473
- def on_before_execution
474
- # eg: Append additional contextual data
475
- end
476
-
477
- def on_after_execution
478
- # eg: Store results to database
479
- end
480
-
481
453
  end
482
454
  ```
483
455
 
484
- ### Status Hooks
456
+ ### State Hooks
485
457
 
486
- Define one or more callbacks that are called after execution for
487
- specific statuses.
458
+ Define one or more callbacks that are called during transitions between states.
488
459
 
489
460
  ```ruby
490
461
  class DecryptSecretMessage < Lite::Command::Base
491
462
 
463
+ on_pending :some_method
464
+ on_executing :some_method
465
+ on_complete :some_method
466
+ on_interrupted :some_method
467
+
492
468
  def call
493
469
  # ...
494
470
  end
495
471
 
496
- private
497
-
498
- def on_success
499
- # eg: Increment KPI counter
500
- end
501
-
502
- def on_noop(fault)
503
- # eg: Log message for posterity
504
- end
505
-
506
- def on_invalid(fault)
507
- # eg: Send metadata errors to frontend
508
- end
509
-
510
- def on_failure(fault)
511
- # eg: Rollback record changes
512
- end
513
-
514
- def on_error(fault_or_exception)
515
- # eg: Report to APM with tags and metadata
516
- end
517
-
518
472
  end
519
473
  ```
520
474
 
521
- > [!NOTE]
522
- > The `on_success` callback does **NOT** take any arguments.
523
-
524
475
  ## Children
525
476
 
526
477
  When building complex commands, its best that you pass the parents context to the
@@ -16,6 +16,7 @@ module Lite
16
16
  base.include Internals::Faults
17
17
  base.include Internals::Calls
18
18
  base.include Internals::Executions
19
+ base.include Internals::Hooks
19
20
  base.include Internals::Results
20
21
 
21
22
  if Lite::Command.configuration.raise_dynamic_faults # rubocop:disable Style/GuardClause
@@ -34,7 +35,7 @@ module Lite
34
35
 
35
36
  def initialize(context = {})
36
37
  @context = Context.build(context)
37
- Utils.try(self, :on_pending)
38
+ run_hooks(:after_initialize)
38
39
  end
39
40
 
40
41
  end
@@ -52,9 +52,9 @@ module Lite
52
52
  private
53
53
 
54
54
  def validate_context_attributes
55
- return if errors.empty?
56
-
57
- invalid!(errors.full_messages.join(". "), metadata: errors.messages)
55
+ run_hooks(:before_validation)
56
+ invalid!(errors.full_messages.join(". "), metadata: errors.messages) unless valid?
57
+ run_hooks(:after_validation)
58
58
  end
59
59
 
60
60
  end
@@ -24,14 +24,12 @@ module Lite
24
24
 
25
25
  def call(context = {})
26
26
  instance = send(:new, context)
27
- instance.validate
28
27
  instance.send(:execute)
29
28
  instance
30
29
  end
31
30
 
32
31
  def call!(context = {})
33
32
  instance = send(:new, context)
34
- instance.validate
35
33
  instance.send(:execute!)
36
34
  instance
37
35
  end
@@ -50,16 +50,18 @@ module Lite
50
50
  increment_execution_index
51
51
  assign_execution_cmd_id
52
52
  start_monotonic_time
53
- Utils.try(self, :on_before_validation)
53
+ run_hooks(:on_pending)
54
54
  validate_context_attributes
55
- Utils.try(self, :on_before_execution)
55
+ run_hooks(:before_execution)
56
56
  executing!
57
- Utils.try(self, :on_executing)
57
+ run_hooks(:on_executing)
58
58
  end
59
59
 
60
60
  def after_execution
61
61
  send(:"#{success? ? COMPLETE : INTERRUPTED}!")
62
- Utils.try(self, :on_after_execution)
62
+ run_hooks(:after_execution)
63
+ run_hooks(:"on_#{status}")
64
+ run_hooks(:"on_#{state}")
63
65
  stop_monotonic_time
64
66
  append_execution_result
65
67
  freeze_execution_objects
@@ -72,26 +74,17 @@ module Lite
72
74
  end
73
75
 
74
76
  def execute
75
- around_execution { call }
76
- Utils.try(self, :on_success)
77
- rescue StandardError => e
78
- fault(e, Utils.try(e, :type) || ERROR, metadata, exception: e)
79
- after_execution
80
- Utils.try(self, :"on_#{status}", e)
81
- ensure
82
- Utils.try(self, :"on_#{state}")
77
+ execute!
78
+ rescue StandardError
79
+ # Do nothing
83
80
  end
84
81
 
85
82
  def execute!
86
83
  around_execution { call }
87
- Utils.try(self, :on_success)
88
84
  rescue StandardError => e
89
85
  fault(e, Utils.try(e, :type) || ERROR, metadata, exception: e)
90
86
  after_execution
91
- Utils.try(self, :"on_#{status}", e)
92
87
  raise(e)
93
- else
94
- Utils.try(self, :"on_#{state}")
95
88
  end
96
89
 
97
90
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lite
4
+ module Command
5
+
6
+ HOOKS = [
7
+ :after_initialize,
8
+ :before_validation,
9
+ :after_validation,
10
+ :before_execution,
11
+ :after_execution,
12
+ *STATUSES.map { |s| :"on_#{s}" },
13
+ *STATES.map { |s| :"on_#{s}" }
14
+ ].freeze
15
+
16
+ module Internals
17
+ module Hooks
18
+
19
+ def self.included(base)
20
+ base.extend ClassMethods
21
+ end
22
+
23
+ module ClassMethods
24
+
25
+ def hooks
26
+ @hooks ||= Utils.try(superclass, :hooks).dup || {}
27
+ end
28
+
29
+ HOOKS.each do |h|
30
+ define_method(h) do |*method_names, &block|
31
+ method_names << block if block_given?
32
+ method_names.each { |mn| (hooks[h] ||= []) << mn }
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ private
39
+
40
+ def run_hooks(hook)
41
+ hooks = self.class.hooks[hook]
42
+ return if hooks.nil?
43
+
44
+ hooks.each { |h| Utils.call(self, h) }
45
+ end
46
+
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -3,7 +3,7 @@
3
3
  module Lite
4
4
  module Command
5
5
 
6
- VERSION = "3.1.5"
6
+ VERSION = "3.2.0"
7
7
 
8
8
  end
9
9
  end
data/lib/lite/command.rb CHANGED
@@ -16,6 +16,7 @@ require "lite/command/internals/attributes"
16
16
  require "lite/command/internals/faults"
17
17
  require "lite/command/internals/calls"
18
18
  require "lite/command/internals/executions"
19
+ require "lite/command/internals/hooks"
19
20
  require "lite/command/internals/results"
20
21
  require "lite/command/base"
21
22
  require "lite/command/step"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lite-command
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.5
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Gomez
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-10-28 00:00:00.000000000 Z
11
+ date: 2024-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -201,6 +201,7 @@ files:
201
201
  - lib/lite/command/internals/calls.rb
202
202
  - lib/lite/command/internals/executions.rb
203
203
  - lib/lite/command/internals/faults.rb
204
+ - lib/lite/command/internals/hooks.rb
204
205
  - lib/lite/command/internals/results.rb
205
206
  - lib/lite/command/internals/runtimes.rb
206
207
  - lib/lite/command/sequence.rb