app/models/foreman_tasks/task/summarizer.rb in foreman-tasks-0.15.1 vs app/models/foreman_tasks/task/summarizer.rb in foreman-tasks-0.15.2
- old
+ new
@@ -1,15 +1,105 @@
module ForemanTasks
class Task::Summarizer
- def summarize_by_status(since = nil)
- result = ::ForemanTasks::Task.where("result <> 'success'")
- .select('count(state) AS count, state, result, max(started_at) AS started_at')
- .group(:state, :result).order(:state)
- result = result.where('started_at > ?', since) if since
- result
+ ENSURED_STATE_KEYS = %w[running paused stopped scheduled].freeze
+ ENSURED_RESULT_KEYS = %w[success error warning].freeze
+
+ # number of recent/total tasks for specific classification (state/result)
+ class Record
+ def initialize
+ @data = { recent: 0, total: 0 }
+ end
+
+ def to_h
+ @data.dup
+ end
+
+ # updates `field` (one of [:recent, :total]) with counts from aggregated_scope
+ def update(field, counts)
+ raise ArgumentError, "Unexpected field #{field}" unless @data.key?(field)
+ @data[field] = counts.sum(&:count)
+ end
end
+ # number of recent/total tasks for specific state + distribution across different results
+ # in `by_result` attribute
+ class RecordWithResult < Record
+ attr_reader :by_result
+
+ def initialize
+ super
+ @by_result = Hash.new { |h, k| h[k] = Record.new }
+ ENSURED_RESULT_KEYS.each { |result_value| @by_result[result_value] = Record.new }
+ end
+
+ def to_h
+ by_result_hash = @by_result.each.with_object({}) do |(result, record), hash|
+ hash[result] = record.to_h
+ end
+ super.update(by_result: by_result_hash)
+ end
+
+ # Updates the `field` summary + grouping by result
+ def update(field, counts)
+ super(field, counts)
+ counts.group_by(&:result).each do |(result, result_counts)|
+ @by_result[result].update(field, result_counts)
+ end
+ end
+ end
+
+ def initialize(recent_timeframe = 24)
+ @recent_timeframe = recent_timeframe.hours
+ end
+
+ def summarize_by_status
+ aggregated_scope.where("result <> 'success'")
+ end
+
def latest_tasks_in_errors_warning(limit = 5)
::ForemanTasks::Task.where('result in (?)', %w[error warning]).order('started_at DESC').limit(limit)
+ end
+
+ # Returns summary of tasks count, grouped by `state` and `result`, if form of:
+ #
+ # { 'running' => { recent: 3, total: 6 },
+ # 'paused' => { recent: 1, total: 3 },
+ # 'stopped' => { recent: 3, total: 7,
+ # by_result: {
+ # 'success' => { recent: 2, total: 4 },
+ # 'warning' => { recent: 1, total: 2 },
+ # 'error' => { recent: 0, total: 1 },
+ # }}
+ # 'scheduled' => { recent: 0, total: 3 }}
+ #
+ def summary
+ @summary = Hash.new { |h, state| h[state] = Record.new }
+ ENSURED_STATE_KEYS.each do |state|
+ @summary[state] = state == 'stopped' ? RecordWithResult.new : Record.new
+ end
+
+ add_to_summary(aggregated_scope, :total)
+ add_to_summary(aggregated_recent_scope, :recent)
+
+ @summary.each.with_object({}) do |(key, record), hash|
+ hash[key] = record.to_h
+ end
+ end
+
+ private
+
+ def add_to_summary(aggregated_scope, field)
+ aggregated_scope.group_by(&:state).each do |(state, state_counts)|
+ @summary[state].update(field, state_counts)
+ end
+ end
+
+ def aggregated_scope
+ ::ForemanTasks::Task.select('count(state) AS count, state, result, max(started_at) AS started_at')
+ .group(:state, :result).order(:state)
+ end
+
+ def aggregated_recent_scope
+ aggregated_scope.where("state_updated_at > ?", Time.now.utc - @recent_timeframe)
end
end
end