5
0
Fork 0
mirror of https://0xacab.org/sutty/sutty synced 2024-11-23 03:16:23 +00:00
panel/app/models/site/index.rb

181 lines
5.6 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
class Site
# Indexa todos los artículos de un sitio
#
# TODO: Hacer opcional
module Index
extend ActiveSupport::Concern
included do
has_many :indexed_posts, dependent: :destroy
MODIFIED_STATUSES = %i[added modified renamed].freeze
2023-09-27 19:20:57 +00:00
LOCALE_FROM_PATH = /\A_/.freeze
def blob_service
@blob_service ||= ActiveStorage::Service::JekyllService.build_for_site(site: self)
end
def index_posts!
Site.transaction do
2022-08-03 16:11:06 +00:00
docs.each(&:index!)
update(last_indexed_commit: repository.head_commit.oid)
end
end
2023-09-27 19:20:57 +00:00
# Encuentra los artículos modificados entre dos commits y los
# reindexa.
def reindex_changes!
return unless reindexable?
Site.transaction do
remove_deleted_posts!
reindex_modified_posts!
update(last_indexed_commit: repository.head_commit.oid)
end
end
# No hacer nada si el repositorio no cambió o no hubo cambios
# necesarios
def reindexable?
return false if last_indexed_commit.blank?
return false if last_indexed_commit == repository.head_commit.oid
!indexable_posts.empty?
end
private
# Trae el último commit indexado desde el repositorio
#
# @return [Rugged::Commit]
def indexed_commit
@indexed_commit ||= repository.rugged.lookup(last_indexed_commit)
end
# Calcula la diferencia entre el último commit indexado y el
# actual
#
# XXX: Esto no tiene en cuenta modificaciones en la historia como
# cambio de ramas, reverts y etc, solo asume que se mueve hacia
# adelante en la misma rama o las dos ramas están relacionadas.
#
# @return [Rugged::Diff]
def diff_with_head
@diff_with_head ||= indexed_commit.diff(repository.head_commit)
end
# Obtiene todos los archivos a reindexar
#
# @return [Array<Rugged::Diff::Delta>]
2023-09-27 19:20:57 +00:00
def indexable_posts
@indexable_posts ||=
diff_with_head.each_delta.select do |delta|
locales.any? do |locale|
delta.old_file[:path].start_with? "_#{locale}/"
end
end
end
2024-02-02 17:07:09 +00:00
# Encuentra todos los archivos estáticos a reindexar, si fueron
# borrados necesitamos saber la ubicación anterior, si son nuevos,
# la nueva.
2024-02-02 15:45:07 +00:00
#
# @return [Array<Rugged::Diff::Delta>]
def indexable_static_files
@indexable_static_files ||=
diff_with_head.each_delta.select do |delta|
2024-02-02 17:07:09 +00:00
(
delta.status == :deleted &&
delta.old_file[:path].start_with?('public/')
) || delta.new_file[:path].start_with?('public/')
2024-02-02 15:45:07 +00:00
end
end
2023-09-27 19:20:57 +00:00
# Elimina los artículos eliminados o que cambiaron de ubicación
# del índice
def remove_deleted_posts!
indexable_posts.select(&:deleted?).each do |delta|
2023-09-27 19:20:57 +00:00
locale, path = locale_and_path_from(delta.old_file[:path])
indexed_posts.destroy_by(locale: locale, path: path).tap do |destroyed_posts|
next unless destroyed_posts.empty?
Rails.logger.info I18n.t('indexed_posts.deleted', site: name, path: path, records: destroyed_posts.count)
end
end
end
2023-09-27 19:20:57 +00:00
2024-02-02 15:45:07 +00:00
# Elimina de ActiveStorage los archivos borrados, renombrados o
# modificados, para poder recalcular su contenido y nueva
# ubicación.
#
# Los renombrados o modificados se vuelven a crear en
# reindex_modified_static_files!
def remove_deleted_or_renamed_static_files!
indexable_static_files.select do |delta|
delta.deleted? || delta.modified? || delta.renamed?
end.each do |delta|
key = blob_service.key_from_path(delta.old_file[:path])
static_files.blobs.find_by(service_name: name, key: key).tap do |blob|
next unless blob
transaction do
static_files.where(blob_id: blob.id).destroy_all
blob.destroy
end
end
end
end
# Reindexa los archivos estáticos modificados
def reindex_modified_static_files!
indexable_static_files.select do |delta|
MODIFIED_STATUSES.include?(delta.status) || delta.renamed?
end.each do |delta|
transaction do
path = blob_service.absolute_path_for(delta.new_file[:path].sub(%r{\Apublic/}, ''))
key = blob_service.key_from_path(path)
pathname = Pathname.new(path)
blob = ActiveStorage::Blob.create_after_unfurling!(key: key, io: pathname.open, filename: pathname.basename, service_name: name)
ActiveStorage::Attachment.create!(name: 'static_files', record: self, blob: blob)
end
end
end
2023-09-27 19:20:57 +00:00
# Reindexa artículos que cambiaron de ubicación, se agregaron
# o fueron modificados
def reindex_modified_posts!
indexable_posts.select do |delta|
MODIFIED_STATUSES.include? delta.status
end.each do |delta|
locale, path = locale_and_path_from(delta.new_file[:path])
posts(lang: locale).find(path).index!
2023-09-27 19:20:57 +00:00
end
end
# Obtiene el idioma y la ruta del post a partir de la ubicación en
# el disco.
#
# Las rutas vienen en ASCII-9BIT desde Rugged, pero en realidad
# son UTF-8
2023-09-27 19:20:57 +00:00
#
# @return [Array<String>]
def locale_and_path_from(path)
locale, path = path.force_encoding('utf-8').split(File::SEPARATOR, 2)
2023-09-27 19:20:57 +00:00
[
locale.sub(LOCALE_FROM_PATH, ''),
File.basename(path, '.*')
]
end
end
end
end