sequencer.rb 2.6 KB

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