Class: GoodJob::ScheduledByQueueChart
- Defined in:
- app/charts/good_job/scheduled_by_queue_chart.rb
Instance Method Summary collapse
- #data ⇒ Object
-
#initialize(filter) ⇒ ScheduledByQueueChart
constructor
A new instance of ScheduledByQueueChart.
Methods inherited from BaseChart
#start_end_binds, #string_to_hsl
Constructor Details
#initialize(filter) ⇒ ScheduledByQueueChart
Returns a new instance of ScheduledByQueueChart.
5 6 7 8 |
# File 'app/charts/good_job/scheduled_by_queue_chart.rb', line 5 def initialize(filter) super() @filter = filter end |
Instance Method Details
#data ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'app/charts/good_job/scheduled_by_queue_chart.rb', line 10 def data binds = start_end_binds start_time, end_time = binds.map(&:value) # Align the inner range predicate to the same hour buckets the outer generate_series # produces. Doing the truncation in SQL (rather than in Ruby with beginning_of_hour) # keeps both sides on the same grid even when the app's time zone has a fractional # offset from UTC (e.g. IST +05:30). AR serializes Time binds as UTC, so the outer # date_trunc operates in UTC, and this predicate must match that. pushdown = <<~SQL.squish "good_jobs"."scheduled_at" >= date_trunc('hour', ?::timestamp) AND "good_jobs"."scheduled_at" < date_trunc('hour', ?::timestamp) + interval '1 hour' SQL inner_sql = @filter.filtered_query .except(:select, :order) .where(pushdown, start_time, end_time) .select(:queue_name, :scheduled_at) .to_sql count_query = <<~SQL.squish SELECT * FROM generate_series( date_trunc('hour', $1::timestamp), date_trunc('hour', $2::timestamp), '1 hour' ) timestamp LEFT JOIN ( SELECT date_trunc('hour', scheduled_at) AS scheduled_at, queue_name, count(*) AS count FROM (#{inner_sql}) sources GROUP BY date_trunc('hour', scheduled_at), queue_name ) sources ON sources.scheduled_at = timestamp ORDER BY timestamp ASC SQL executions_data = GoodJob::Job.connection_pool.with_connection { |conn| conn.exec_query(GoodJob::Job.pg_or_jdbc_query(count_query), "GoodJob Dashboard Chart", binds) } queue_names = executions_data.reject { |d| d['count'].nil? }.map { |d| d['queue_name'] || BaseFilter::EMPTY }.uniq labels = [] queues_data = executions_data.to_a.group_by { |d| d['timestamp'] }.each_with_object({}) do |(, values), hash| labels << .in_time_zone.strftime('%H:%M') queue_names.each do |queue_name| (hash[queue_name] ||= []) << values.find { |d| d['queue_name'] == queue_name }&.[]('count') end end { type: "line", data: { labels: labels, datasets: queues_data.map do |queue, data| label = queue || '(none)' { label: label, data: data, backgroundColor: string_to_hsl(label), borderColor: string_to_hsl(label), } end, }, options: { scales: { y: { beginAtZero: true, }, }, }, } end |