From 10580d2b4f169be9643f13c2335d44e3f95a9ef6 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 10 May 2021 10:56:08 -0300 Subject: [PATCH 1/3] compilar el sitio de a uno por vez MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit estamos deshabilitando el botón en el panel, pero gracias a la caché (o si le usuarie tiene el botón ya abierto y habilitado) es posible correr dos o más tareas de compilación a la vez, lo que produce errores. por ejemplo, que una compilación falle porque quiere comprimir archivos que ya no están. con este cambio, si un sitio está compilando, la tarea se aplaza un minuto. si hay muchas tareas, eventualmente se harán todas pero no se pisan entre sí. quizás lo correcto sería hacerlo cuando se lanza la compilación también. --- app/jobs/deploy_job.rb | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/jobs/deploy_job.rb b/app/jobs/deploy_job.rb index 98e474ac..e5e051c7 100644 --- a/app/jobs/deploy_job.rb +++ b/app/jobs/deploy_job.rb @@ -8,13 +8,20 @@ class DeployJob < ApplicationJob def perform(site, notify = true) ActiveRecord::Base.connection_pool.with_connection do @site = Site.find(site) - @site.update_attribute :status, 'building' + + # Si ya hay una tarea corriendo, aplazar esta + if @site.status == 'building' + DeployJob.perform_in(60, site, notify) + return + end + + @site.update status: 'building' # Asegurarse que DeployLocal sea el primero! @deployed = { deploy_local: deploy_locally } # No es opcional unless @deployed[:deploy_local] - @site.update_attribute :status, 'waiting' + @site.update status: 'waiting' notify_usuaries if notify # Hacer fallar la tarea @@ -23,7 +30,7 @@ class DeployJob < ApplicationJob deploy_others notify_usuaries if notify - @site.update_attribute :status, 'waiting' + @site.update status: 'waiting' end end # rubocop:enable Metrics/MethodLength From 39eb584a97ebca66c83e591d29e52fd4c6d9c7ad Mon Sep 17 00:00:00 2001 From: f Date: Mon, 10 May 2021 13:14:02 -0300 Subject: [PATCH 2/3] no compilar varias veces desde el compilador MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit esto evita que se espamee el botón de publicar --- app/jobs/deploy_job.rb | 2 +- app/models/site.rb | 13 ++++++++++++- test/controllers/sites_controller_test.rb | 7 +++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/app/jobs/deploy_job.rb b/app/jobs/deploy_job.rb index e5e051c7..f1ceca9e 100644 --- a/app/jobs/deploy_job.rb +++ b/app/jobs/deploy_job.rb @@ -10,7 +10,7 @@ class DeployJob < ApplicationJob @site = Site.find(site) # Si ya hay una tarea corriendo, aplazar esta - if @site.status == 'building' + if @site.building? DeployJob.perform_in(60, site, notify) return end diff --git a/app/models/site.rb b/app/models/site.rb index 7a8b4b4b..7aeb8a9b 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -315,14 +315,25 @@ class Site < ApplicationRecord # Poner en la cola de compilación def enqueue! - !enqueued? && update_attribute(:status, 'enqueued') + waiting? && update(status: 'enqueued') end # Está en la cola de compilación? + # + # TODO: definir todos estos métodos dinámicamente, aunque todavía no + # tenemos una máquina de estados propiamente dicha. def enqueued? status == 'enqueued' end + def waiting? + status == 'waiting' + end + + def building? + status == 'building' + end + # Cargar el sitio Jekyll # # TODO: En lugar de leer todo junto de una vez, extraer la carga de diff --git a/test/controllers/sites_controller_test.rb b/test/controllers/sites_controller_test.rb index 5f67092a..a7e2f68b 100644 --- a/test/controllers/sites_controller_test.rb +++ b/test/controllers/sites_controller_test.rb @@ -102,6 +102,13 @@ class SitesControllerTest < ActionDispatch::IntegrationTest 'index.html')) end + test 'no se pueden encolar varias veces seguidas' do + assert_enqueued_jobs 2 do + post site_enqueue_url(@site), headers: @authorization + post site_enqueue_url(@site), headers: @authorization + end + end + test 'se pueden actualizar' do name = SecureRandom.hex design = Design.all.where.not(id: @site.design_id).sample From 8d7e4d2b6406ee9a34204e94454ff4c4a84e7ad8 Mon Sep 17 00:00:00 2001 From: f Date: Mon, 10 May 2021 13:55:36 -0300 Subject: [PATCH 3/3] solo poner en cola una sola vez MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit el cambio anterior no permitía que se encolen varias compilaciones y la versión actual pone el sitio en cola mientras se está compilando. con este cambio el sitio se puede encolar varias veces pero el estado se cambia una sola vez, para no abrirle la puerta a un loop infinito de compilaciones. lo correcto sería generar un modelo de cola con su propio estado (y probablemente a partir de cuál commit se está compilando). --- app/controllers/sites_controller.rb | 3 ++- app/models/site.rb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/controllers/sites_controller.rb b/app/controllers/sites_controller.rb index d7d2f9f6..22429f35 100644 --- a/app/controllers/sites_controller.rb +++ b/app/controllers/sites_controller.rb @@ -63,7 +63,8 @@ class SitesController < ApplicationController authorize site # XXX: Convertir en una máquina de estados? - DeployJob.perform_async site.id if site.enqueue! + site.enqueue! + DeployJob.perform_async site.id redirect_to site_posts_path(site) end diff --git a/app/models/site.rb b/app/models/site.rb index 7aeb8a9b..683541e4 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -315,7 +315,7 @@ class Site < ApplicationRecord # Poner en la cola de compilación def enqueue! - waiting? && update(status: 'enqueued') + update(status: 'enqueued') if waiting? end # Está en la cola de compilación?