Class: Sessions::GeolocateJob

Inherits:
Object
  • Object
show all
Defined in:
lib/sessions/jobs/geolocate_job.rb

Overview

Async geo enrichment for the MaxMind path (the Cloudflare path is a free synchronous header read at request time and never gets here). Enqueued after commit — only when trackdown is present AND has a database (see Sessions::Geolocation.async_capable?), so hosts without MaxMind never see a no-op job.

The conditional superclass keeps the constant loadable (Zeitwerk eager loads this file) in the rare host that runs without ActiveJob — where enqueueing is already guarded off.

Instance Method Summary collapse

Instance Method Details

#perform(class_name, id) ⇒ Object



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
# File 'lib/sessions/jobs/geolocate_job.rb', line 17

def perform(class_name, id)
  record = class_name.constantize.find_by(id: id)
  return unless record.respond_to?(:country_code)
  return if record.country_code.present?

  ip = record.try(:ip_address)
  return if ip.blank?
  return unless defined?(::Trackdown)

  result = ::Trackdown.locate(ip.to_s)
  updates = Sessions::Geolocation.columns_from(result)
  return if updates.empty?

  # Events also store precision-reduced coordinates (privacy now,
  # impossible-travel math later); registry rows don't have the
  # columns and the filter drops them.
  updates.merge!(Sessions::Geolocation.coordinates_from(result))
  updates.select! { |column, _| record.class.column_names.include?(column.to_s) }

  record.update_columns(updates) if updates.any?

  (record, updates)
rescue StandardError => e
  Sessions.warn("geolocate job failed: #{e.class}: #{e.message}")
end