blazer.rb 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. require "csv"
  2. require "chartkick"
  3. require "blazer/version"
  4. require "blazer/engine"
  5. require "blazer/tasks"
  6. module Blazer
  7. class << self
  8. attr_accessor :audit
  9. attr_reader :time_zone
  10. attr_accessor :user_name
  11. attr_accessor :user_class
  12. attr_accessor :timeout
  13. attr_accessor :from_email
  14. end
  15. self.audit = true
  16. self.user_name = :name
  17. self.timeout = 15
  18. def self.time_zone=(time_zone)
  19. @time_zone = time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone[time_zone.to_s]
  20. end
  21. def self.settings
  22. @settings ||= YAML.load(File.read(Rails.root.join("config", "blazer.yml")))
  23. end
  24. def self.linked_columns
  25. settings["linked_columns"] || {}
  26. end
  27. def self.smart_columns
  28. settings["smart_columns"] || {}
  29. end
  30. def self.smart_variables
  31. settings["smart_variables"] || {}
  32. end
  33. def self.run_statement(statement)
  34. rows = []
  35. error = nil
  36. begin
  37. Blazer::Connection.transaction do
  38. Blazer::Connection.connection.execute("SET statement_timeout = #{Blazer.timeout * 1000}") if Blazer.timeout && postgresql?
  39. result = Blazer::Connection.connection.select_all(statement)
  40. result.each do |untyped_row|
  41. row = {}
  42. untyped_row.each do |k, v|
  43. row[k] = result.column_types.empty? ? v : result.column_types[k].send(:type_cast, v)
  44. end
  45. rows << row
  46. end
  47. raise ActiveRecord::Rollback
  48. end
  49. rescue ActiveRecord::StatementInvalid => e
  50. error = e.message.sub(/.+ERROR: /, "")
  51. end
  52. [rows, error]
  53. end
  54. def self.tables
  55. default_schema = postgresql? ? "public" : Blazer::Connection.connection_config[:database]
  56. schema = Blazer::Connection.connection_config[:schema] || default_schema
  57. rows, error = run_statement(Blazer::Connection.send(:sanitize_sql_array, ["SELECT table_name, column_name, ordinal_position, data_type FROM information_schema.columns WHERE table_schema = ?", schema]))
  58. Hash[rows.group_by { |r| r["table_name"] }.map { |t, f| [t, f.sort_by { |f| f["ordinal_position"] }.map { |f| f.slice("column_name", "data_type") }] }.sort_by { |t, _f| t }]
  59. end
  60. def self.postgresql?
  61. Blazer::Connection.connection.adapter_name == "PostgreSQL"
  62. end
  63. def self.run_checks
  64. Blazer::Check.includes(:blazer_query).find_each do |check|
  65. rows, error = run_statement(check.blazer_query.statement)
  66. check.update_state(rows, error)
  67. end
  68. end
  69. def self.send_failing_checks
  70. emails = {}
  71. Blazer::Check.includes(:blazer_query).where(state: %w[failing error]).find_each do |check|
  72. check.emails.to_s.split(",").map(&:strip).each do |email|
  73. (emails[email] ||= []) << check
  74. end
  75. end
  76. emails.each do |email, checks|
  77. Blazer::CheckMailer.failing_checks(email, checks).deliver_later
  78. end
  79. end
  80. end