diff --git a/app/models/communication/website.rb b/app/models/communication/website.rb index 436e64114..6750e73a7 100644 --- a/app/models/communication/website.rb +++ b/app/models/communication/website.rb @@ -45,17 +45,20 @@ # default_language_id :uuid not null, indexed # deuxfleurs_access_key_id :string # locked_by_job_id :uuid +# synchronization_locked_by_id :uuid indexed # university_id :uuid not null, indexed # # Indexes # -# index_communication_websites_on_about (about_type,about_id) -# index_communication_websites_on_default_language_id (default_language_id) -# index_communication_websites_on_university_id (university_id) +# index_communication_websites_on_about (about_type,about_id) +# index_communication_websites_on_default_language_id (default_language_id) +# index_communication_websites_on_synchronization_locked_by_id (synchronization_locked_by_id) +# index_communication_websites_on_university_id (university_id) # # Foreign Keys # # fk_rails_2b6d929310 (default_language_id => languages.id) +# fk_rails_49c2afa13d (synchronization_locked_by_id => users.id) ON DELETE => nullify # fk_rails_bb6a496c08 (university_id => universities.id) # class Communication::Website < ApplicationRecord diff --git a/app/models/communication/website/with_git_repository.rb b/app/models/communication/website/with_git_repository.rb index fa7d24049..ec455952a 100644 --- a/app/models/communication/website/with_git_repository.rb +++ b/app/models/communication/website/with_git_repository.rb @@ -2,6 +2,10 @@ module Communication::Website::WithGitRepository extend ActiveSupport::Concern included do + belongs_to :synchronization_locked_by, + class_name: 'User', + optional: true + has_many :website_git_files, class_name: 'Communication::Website::GitFile', dependent: :destroy @@ -31,6 +35,19 @@ def git_repository @git_repository ||= Git::Repository.new self end + def synchronization_locked? + synchronization_locked_by_id.present? + end + + def lock_synchronization!(user) + update_column :synchronization_locked_by_id, user.id + end + + def unlock_synchronization! + update_column :synchronization_locked_by_id, nil + sync_with_git if desynchronized_generated_git_files.any? + end + def repository_url git_repository.url end @@ -44,11 +61,13 @@ def identify_git_files_safely end def sync_with_git + return if synchronization_locked? update_column(:last_sync_at, Time.now) Communication::Website::SyncWithGitJob.perform_later(id) end def sync_with_git_safely + return if synchronization_locked? return unless git_repository.valid? git_repository.git_files = git_files.generated .desynchronized_until(last_sync_at) @@ -102,10 +121,12 @@ def should_clean_on_git? end def update_theme_version + return if synchronization_locked? Communication::Website::UpdateThemeVersionJob.perform_later(id) end def update_theme_version_safely + return if synchronization_locked? return unless git_repository.valid? git_repository.update_theme_version! end diff --git a/db/migrate/20260903090000_add_synchronization_locked_by_to_communication_websites.rb b/db/migrate/20260903090000_add_synchronization_locked_by_to_communication_websites.rb new file mode 100644 index 000000000..e803e6353 --- /dev/null +++ b/db/migrate/20260903090000_add_synchronization_locked_by_to_communication_websites.rb @@ -0,0 +1,11 @@ +class AddSynchronizationLockedByToCommunicationWebsites < ActiveRecord::Migration[8.1] + def change + add_reference :communication_websites, + :synchronization_locked_by, + type: :uuid, + foreign_key: { + to_table: :users, + on_delete: :nullify + } + end +end diff --git a/db/schema.rb b/db/schema.rb index a22bb880b..d897fc023 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.1].define(version: 2026_08_29_043355) do +ActiveRecord::Schema[8.1].define(version: 2026_09_03_090000) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" enable_extension "pg_stat_statements" @@ -1661,6 +1661,7 @@ t.string "repository" t.text "style" t.date "style_updated_at" + t.uuid "synchronization_locked_by_id" t.string "theme_version", default: "NA" t.uuid "university_id", null: false t.datetime "updated_at", null: false @@ -1668,6 +1669,7 @@ t.integer "years_before_archive_content", default: 3 t.index ["about_type", "about_id"], name: "index_communication_websites_on_about" t.index ["default_language_id"], name: "index_communication_websites_on_default_language_id" + t.index ["synchronization_locked_by_id"], name: "index_communication_websites_on_synchronization_locked_by_id" t.index ["university_id"], name: "index_communication_websites_on_university_id" end @@ -3016,6 +3018,7 @@ add_foreign_key "communication_website_posts", "universities" add_foreign_key "communication_websites", "languages", column: "default_language_id" add_foreign_key "communication_websites", "universities" + add_foreign_key "communication_websites", "users", column: "synchronization_locked_by_id", on_delete: :nullify add_foreign_key "education_diploma_localizations", "education_diplomas", column: "about_id" add_foreign_key "education_diploma_localizations", "languages" add_foreign_key "education_diploma_localizations", "universities" diff --git a/test/models/communication/website/with_git_repository_test.rb b/test/models/communication/website/with_git_repository_test.rb new file mode 100644 index 000000000..04dfe8d6d --- /dev/null +++ b/test/models/communication/website/with_git_repository_test.rb @@ -0,0 +1,35 @@ +require "test_helper" + +# rails test test/models/communication/website/with_git_repository_test.rb +class Communication::Website::WithGitRepositoryTest < ActiveSupport::TestCase + include ActiveJob::TestHelper + + test "lock and unlock synchronization" do + refute website_with_github.synchronization_locked? + website_with_github.lock_synchronization! users(:admin) + assert website_with_github.synchronization_locked? + website_with_github.unlock_synchronization! + refute website_with_github.synchronization_locked? + end + + test "jobs are enqueued only when unlocked" do + # Locked: nothing is enqueued + website_with_github.lock_synchronization! users(:admin) + assert_no_enqueued_jobs do + website_with_github.sync_with_git + website_with_github.sync_with_git_safely + website_with_github.update_theme_version + end + + # Unlocking re-triggers a sync for desynchronized generated git files + assert_enqueued_jobs 1, only: Communication::Website::SyncWithGitJob do + website_with_github.unlock_synchronization! + end + + # Unlocked: jobs run normally + assert_enqueued_jobs 1, only: Communication::Website::UpdateThemeVersionJob do + website_with_github.update_theme_version + end + + end +end