# frozen_string_literal: true # Procesa los errores de JavaScript class BacktraceJob < ApplicationJob queue_as :low_priority attr_reader :errors def perform(site_id:, errors:) @errors = errors errors.each do |error| error['backtrace'].each do |backtrace| offset = SourceMap::Offset.new(backtrace['line'], backtrace['column']) mapping = sourcemap.bsearch(offset) next unless mapping backtrace['file'] = mapping.source backtrace['line'] = mapping.original.line backtrace['column'] = mapping.original.column end end begin raise NoMethodError rescue NoMethodError => e ExceptionNotifier.notify_exception(e, data: { errors: errors }) end end private # Obtiene todos los archivos del backtrace def files @files ||= errors.map { |x| x['backtrace'] }.flatten.map { |x| x['file'].split('@').last }.uniq end # Asume que todos los sourcemaps comparten la misma URL, lo # correcto serĂ­a buscarlo en sourceMappingURL al final de cada # archivo. # # Descarga los archivos y obtiene el backtrace original. def sourcemap @sourcemap ||= begin files.map { |x| "#{x}.map" }.map do |x| data = FastJsonparser.parse(Rails.cache.fetch(x, expires_in: 12.hours) do Down.open(x).read end, symbolize_keys: false) SourceMap::Map.from_hash data rescue Down::Error, FastJsonparser::Error SourceMap::Map.new end.reduce(&:+) end end end