sequencer.rb 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. require_dependency 'mixin/rails_logger'
  2. require_dependency 'mixin/start_finish_logger'
  3. class Sequencer
  4. include ::Mixin::RailsLogger
  5. include ::Mixin::StartFinishLogger
  6. attr_reader :sequence
  7. # Convenience wrapper for instant processing with the given attributes.
  8. #
  9. # @example
  10. # Sequencer.process('Example::Sequence')
  11. #
  12. # @example
  13. # Sequencer.process('Example::Sequence',
  14. # parameters: {
  15. # some: 'value',
  16. # },
  17. # expecting: [:result, :answer]
  18. # )
  19. #
  20. # @return [Hash{Symbol => Object}] the final result state attributes and values
  21. def self.process(sequence, *args)
  22. new(sequence, *args).process
  23. end
  24. # Provides the log level definition for the requested Sequencer component.
  25. #
  26. # @example
  27. # Sequencer.log_level_for(:state)
  28. # #=> { get: :debug, set: :debug, ... }
  29. #
  30. # @return [ActiveSupport::HashWithIndifferentAcces] the log level definition
  31. def self.log_level_for(component)
  32. Setting.get('sequencer_log_level').with_indifferent_access[component]
  33. end
  34. # Initializes a new Sequencer instance for the given Sequence with parameters and expecting result.
  35. #
  36. # @example
  37. # Sequencer.new('Example::Sequence')
  38. #
  39. # @example
  40. # Sequencer.new('Example::Sequence',
  41. # parameters: {
  42. # some: 'value',
  43. # },
  44. # expecting: [:result, :answer]
  45. # )
  46. def initialize(sequence, parameters: {}, expecting: nil)
  47. @sequence = Sequencer::Sequence.constantize(sequence)
  48. @parameters = parameters
  49. @expecting = expecting
  50. # fall back to sequence default expecting if no explicit
  51. # expecting was given for this sequence
  52. return if !@expecting.nil?
  53. @expecting = @sequence.expecting
  54. end
  55. # Processes the Sequence the instance was initialized with.
  56. #
  57. # @example
  58. # sequence.process
  59. #
  60. # @return [Hash{Symbol => Object}] the final result state attributes and values
  61. def process
  62. log_start_finish(log_level[:start_finish], "Sequence '#{sequence.name}'") do
  63. sequence.units.each_with_index do |unit, index|
  64. state.process do
  65. log_start_finish(log_level[:unit], "Sequence '#{sequence.name}' Unit '#{unit.name}' (index: #{index})") do
  66. unit.process(state)
  67. end
  68. end
  69. end
  70. end
  71. state.to_h.tap do |result|
  72. logger.public_send(log_level[:result]) { "Returning Sequence '#{sequence.name}' result: #{result.inspect}" }
  73. end
  74. end
  75. private
  76. def state
  77. @state ||= Sequencer::State.new(sequence,
  78. parameters: @parameters,
  79. expecting: @expecting)
  80. end
  81. def log_level
  82. @log_level ||= self.class.log_level_for(:sequence)
  83. end
  84. end