# frozen_string_literal: true # Procesar una lista de URIs para una lista de dominios. Esto nos # permite procesar estadísticas a demanda. # # Hay varias cosas acá que van a convertirse en métodos propios, como la # detección de URIs de un sitio (aunque la versión actual detecta todas # las páginas y no solo las de posts como tenemos planeado, hay que # resolver eso). # # Los hostnames de un sitio van a poder obtenerse a partir de # Site#hostnames con la garantía de que son únicos. class UriCollectionJob < PeriodicJob # Ignoramos imágenes porque suelen ser demasiadas y no aportan a las # estadísticas. IMAGES = %w[.png .jpg .jpeg .gif .webp .jfif].freeze STAT_NAME = 'uri_collection_job' def perform(site_id:, once: true) @site = Site.find site_id # Recordar la última vez que se corrió la tarea stat = site.stats.create! name: STAT_NAME hostnames.each do |hostname| uris.each do |uri| next if stop? AccessLog.where(host: hostname, uri: uri) .where('created_at >= ?', beginning_of_interval) .completed_requests .non_robots .group(:host, :uri) .rollup('host|uri', interval: starting_interval, update: true) # Reducir las estadísticas calculadas aplicando un rollup sobre el # intervalo más amplio. Stat::INTERVALS.reduce do |previous, current| beginning_of_this_interval = beginning_of_interval.try(:"beginning_of_#{current}") Rollup.where(name: 'host|uri', interval: previous) .where('time >= ?', beginning_of_this_interval) .where_dimensions(host: hostname, uri: uri) .group("dimensions->'host'", "dimensions->'uri'") .rollup('host|uri', interval: current, update: true) do |rollup| rollup.sum(:value) end # Devolver el intervalo actual current end end end stat.touch run_again! unless once end private def stat_name STAT_NAME end # @return [String] # # TODO: Cambiar al mergear origin-referer def destination @destination ||= site.deploys.find_by(type: 'DeployLocal').destination end # TODO: Cambiar al mergear origin-referer # # @return [Array] def hostnames @hostnames ||= site.deploys.map do |deploy| case deploy when DeployLocal site.hostname when DeployWww deploy.fqdn when DeployAlternativeDomain deploy.hostname.dup.tap do |h| h.replace(h.end_with?('.') ? h[0..-2] : "#{h}.#{Site.domain}") end when DeployHiddenService deploy.onion end end.compact end # Recolecta todas las URIs menos imágenes # # @return [Array] def uris @uris ||= locales.map do |locale| uri = "/#{locale}/".squeeze('/') dir = File.join(destination, locale) files(dir).map do |f| uri + f end end.flatten(2) end # @return [Array] def locales @locales ||= ['', site.locales.map(&:to_s)].flatten(1) end # @param :dir [String] # @return [Array] def files(dir) Dir.chdir(dir) do pages = Dir.glob('**/*.html') files = Dir.glob('public/**/*') files = remove_directories files files = remove_images files [pages, files].flatten(1) end end # @param :files [Array] # @return [Array] def remove_directories(files) files.reject do |f| File.directory? f end end def remove_images(files) files.reject do |f| IMAGES.include? File.extname(f).downcase end end end