Skip to content

Instantly share code, notes, and snippets.

@Sdy603
Created April 9, 2025 17:41
Show Gist options
  • Select an option

  • Save Sdy603/326a4e092838d09e5ac5bd4599612283 to your computer and use it in GitHub Desktop.

Select an option

Save Sdy603/326a4e092838d09e5ac5bd4599612283 to your computer and use it in GitHub Desktop.
# frozen_string_literal: true
require "csv"
require "json"
require "time"
class BackfillIncidentsJob
include Sidekiq::Job
sidekiq_options retry: 0
def perform(csv_data)
@failed_rows = []
incident_rows(csv_data).each do |row|
Incident.transaction do
row[:services].each do |service_name|
service = CreateService.call(name: service_name)
CreateServiceIdentity.call(
name: service_name,
source: "backfill",
source_id: service_name,
service_id: service&.id
)
end
incident = CreateIncident.call(
source: "backfill",
source_id: row[:reference_id],
name: row[:name],
priority: row[:priority],
source_url: row[:source_url],
started_at: row[:started_at],
resolved_at: row[:resolved_at],
service_source_ids: row[:services]
)
if row[:metadata].present?
metadata = ProcessMetadata.call(row[:metadata])
now = Time.current
incident.metadata.upsert_all(
metadata.map { |item| item.merge(row_created_at: now, row_updated_at: now) },
unique_by: [:incident_id, :key]
)
end
end
rescue => e
row[:error_message] = e.message
@failed_rows << row
end
Rails.logger.error("Failed to backfill incidents:\n#{@failed_rows}") if @failed_rows.any?
end
private
def incident_rows(csv_data)
now = Time.current
csv_data.map do |row|
{
reference_id: row["reference_id"],
name: row["name"],
priority: row["priority"],
source_url: row["source_url"],
services: parse_services(row["services"]),
started_at: parse_time(row["started_at"]),
resolved_at: row["resolved_at"].present? ? parse_time(row["resolved_at"]) : nil,
metadata: parse_metadata(row["metadata"]),
row_created_at: now,
row_updated_at: now
}
rescue => e
row[:error_message] = e.message
@failed_rows << row
nil
end.compact
end
def parse_services(raw)
services = raw.to_s.split(",").map(&:strip).reject(&:empty?)
raise "Missing or empty services array" if services.empty?
services
end
def parse_time(value)
return nil if value.blank?
Time.iso8601(value)
rescue ArgumentError
raise "Invalid ISO-8601 timestamp: #{value.inspect}"
end
def parse_metadata(value)
return {} if value.blank?
parsed = JSON.parse(value)
raise "Metadata must be a JSON object" unless parsed.is_a?(Hash)
parsed
rescue JSON::ParserError
raise "Metadata is not valid JSON"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment