Merge branch 'issue-13780' into 'rails'
ci/woodpecker/push/woodpecker Pipeline was successful Details

#13780

See merge request sutty/sutty!210
This commit is contained in:
fauno 2023-10-25 14:30:02 +00:00
commit 9df84e7778
4 changed files with 132 additions and 3 deletions

View File

@ -1,20 +1,125 @@
# frozen_string_literal: true
# Indexa todos los artículos de un sitio
#
# TODO: Hacer opcional
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].freeze
DELETED_STATUSES = %i[deleted].freeze
LOCALE_FROM_PATH = /\A_/.freeze
def index_posts!
Site.transaction do
docs.each(&:index!)
update(last_indexed_commit: repository.head_commit.oid)
end
end
# 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::Delta>]
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
# Elimina los artículos eliminados o que cambiaron de ubicación
# del índice
def remove_deleted_posts!
indexable_posts.select do |delta|
DELETED_STATUSES.include? delta.status
end.each do |delta|
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
# 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!
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
#
# @return [Array<String>]
def locale_and_path_from(path)
locale, path = path.force_encoding('utf-8').split(File::SEPARATOR, 2)
[
locale.sub(LOCALE_FROM_PATH, ''),
File.basename(path, '.*')
]
end
end
end
end

View File

@ -171,6 +171,7 @@ en:
usuarie: User
licencia: License
design: Design
indexed_post: Indexed post
attributes:
usuarie:
email: 'E-mail address'
@ -733,3 +734,5 @@ en:
build_stats:
index:
title: "Publications"
indexed_posts:
deleted: "Deleted indexed post %{path} from %{site} (records: %{records})"

View File

@ -171,6 +171,7 @@ es:
usuarie: Usuarie
licencia: Licencia
design: Diseño
indexed_post: Artículo indexado
attributes:
usuarie:
email: 'Correo electrónico'
@ -741,3 +742,5 @@ es:
build_stats:
index:
title: "Publicaciones"
indexed_posts:
deleted: "Eliminado artículo %{path} de %{site} (filas: %{records})"

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
# Almacenar el último commit indexado
class AddLastIndexedCommitToSites < ActiveRecord::Migration[6.1]
def up
add_column :sites, :last_indexed_commit, :string, null: true
Site.find_each do |site|
site.update_columns(last_indexed_commit: site.repository.head_commit.oid)
rescue Rugged::Error, Rugged::OSError => e
puts "Falló #{site.name}, ignorando: #{e.message}"
end
end
def down
remove_column :sites, :last_indexed_commit
end
end