Add delay to profile updates to debounce them (#34137)
Some checks failed
Bundler Audit / security (push) Waiting to run
Check i18n / check-i18n (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (ruby) (push) Waiting to run
Check formatting / lint (push) Waiting to run
Haml Linting / lint (push) Waiting to run
JavaScript Linting / lint (push) Waiting to run
Ruby Linting / lint (push) Waiting to run
JavaScript Testing / test (push) Waiting to run
Historical data migration test / test (14-alpine) (push) Waiting to run
Historical data migration test / test (15-alpine) (push) Waiting to run
Historical data migration test / test (16-alpine) (push) Waiting to run
Historical data migration test / test (17-alpine) (push) Waiting to run
Ruby Testing / build (production) (push) Waiting to run
Ruby Testing / build (test) (push) Waiting to run
Ruby Testing / test (.ruby-version) (push) Blocked by required conditions
Ruby Testing / test (3.2) (push) Blocked by required conditions
Ruby Testing / test (3.3) (push) Blocked by required conditions
Ruby Testing / Libvips tests (.ruby-version) (push) Blocked by required conditions
Ruby Testing / Libvips tests (3.2) (push) Blocked by required conditions
Ruby Testing / Libvips tests (3.3) (push) Blocked by required conditions
Ruby Testing / End to End testing (.ruby-version) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.2) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.3) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:8.10.2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, opensearchproject/opensearch:2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.2, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.3, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Crowdin / Download translations / download-translations (push) Has been cancelled

This commit is contained in:
Claire 2025-03-11 17:17:17 +01:00 committed by GitHub
parent 725a68d273
commit 420ffdfb62
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 17 additions and 23 deletions

View File

@ -14,7 +14,7 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
@account = current_account
UpdateAccountService.new.call(@account, account_params, raise_error: true)
current_user.update(user_params) if user_params
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
ActivityPub::UpdateDistributionWorker.perform_in(ActivityPub::UpdateDistributionWorker::DEBOUNCE_DELAY, @account.id)
render json: @account, serializer: REST::CredentialAccountSerializer
rescue ActiveRecord::RecordInvalid => e
render json: ValidationErrorFormatter.new(e).as_json, status: 422

View File

@ -7,7 +7,7 @@ class Api::V1::Profile::AvatarsController < Api::BaseController
def destroy
@account = current_account
UpdateAccountService.new.call(@account, { avatar: nil }, raise_error: true)
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
ActivityPub::UpdateDistributionWorker.perform_in(ActivityPub::UpdateDistributionWorker::DEBOUNCE_DELAY, @account.id)
render json: @account, serializer: REST::CredentialAccountSerializer
end
end

View File

@ -7,7 +7,7 @@ class Api::V1::Profile::HeadersController < Api::BaseController
def destroy
@account = current_account
UpdateAccountService.new.call(@account, { header: nil }, raise_error: true)
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
ActivityPub::UpdateDistributionWorker.perform_in(ActivityPub::UpdateDistributionWorker::DEBOUNCE_DELAY, @account.id)
render json: @account, serializer: REST::CredentialAccountSerializer
end
end

View File

@ -8,7 +8,7 @@ module Settings
def destroy
if valid_picture?
if UpdateAccountService.new.call(@account, { @picture => nil, "#{@picture}_remote_url" => '' })
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
ActivityPub::UpdateDistributionWorker.perform_in(ActivityPub::UpdateDistributionWorker::DEBOUNCE_DELAY, @account.id)
redirect_to settings_profile_path, notice: I18n.t('generic.changes_saved_msg'), status: 303
else
redirect_to settings_profile_path

View File

@ -8,7 +8,7 @@ class Settings::PrivacyController < Settings::BaseController
def update
if UpdateAccountService.new.call(@account, account_params.except(:settings))
current_user.update!(settings_attributes: account_params[:settings])
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
ActivityPub::UpdateDistributionWorker.perform_in(ActivityPub::UpdateDistributionWorker::DEBOUNCE_DELAY, @account.id)
redirect_to settings_privacy_path, notice: I18n.t('generic.changes_saved_msg')
else
render :show

View File

@ -9,7 +9,7 @@ class Settings::ProfilesController < Settings::BaseController
def update
if UpdateAccountService.new.call(@account, account_params)
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
ActivityPub::UpdateDistributionWorker.perform_in(ActivityPub::UpdateDistributionWorker::DEBOUNCE_DELAY, @account.id)
redirect_to settings_profile_path, notice: I18n.t('generic.changes_saved_msg')
else
@account.build_fields

View File

@ -8,7 +8,7 @@ class Settings::VerificationsController < Settings::BaseController
def update
if UpdateAccountService.new.call(@account, account_params)
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
ActivityPub::UpdateDistributionWorker.perform_in(ActivityPub::UpdateDistributionWorker::DEBOUNCE_DELAY, @account.id)
redirect_to settings_verification_path, notice: I18n.t('generic.changes_saved_msg')
else
render :show

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true
class ActivityPub::UpdateDistributionWorker < ActivityPub::RawDistributionWorker
DEBOUNCE_DELAY = 5.seconds
sidekiq_options queue: 'push', lock: :until_executed, lock_ttl: 1.day.to_i
# Distribute an profile update to servers that might have a copy

View File

@ -53,8 +53,6 @@ RSpec.describe 'credentials API' do
patch '/api/v1/accounts/update_credentials', headers: headers, params: params
end
before { allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async) }
let(:params) do
{
avatar: fixture_file_upload('avatar.gif', 'image/gif'),
@ -113,7 +111,7 @@ RSpec.describe 'credentials API' do
})
expect(ActivityPub::UpdateDistributionWorker)
.to have_received(:perform_async).with(user.account_id)
.to have_enqueued_sidekiq_job(user.account_id)
end
def expect_account_updates

View File

@ -15,10 +15,6 @@ RSpec.describe 'Deleting profile images' do
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
describe 'DELETE /api/v1/profile' do
before do
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
end
context 'when deleting an avatar' do
context 'with wrong scope' do
before do
@ -38,7 +34,8 @@ RSpec.describe 'Deleting profile images' do
account.reload
expect(account.avatar).to_not exist
expect(account.header).to exist
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id)
expect(ActivityPub::UpdateDistributionWorker)
.to have_enqueued_sidekiq_job(account.id)
end
end
@ -61,7 +58,8 @@ RSpec.describe 'Deleting profile images' do
account.reload
expect(account.avatar).to exist
expect(account.header).to_not exist
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id)
expect(ActivityPub::UpdateDistributionWorker)
.to have_enqueued_sidekiq_job(account.id)
end
end
end

View File

@ -11,8 +11,6 @@ RSpec.describe 'Settings Privacy' do
before { user.account.update(discoverable: false) }
context 'with a successful update' do
before { allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async) }
it 'updates user profile information' do
# View settings page
visit settings_privacy_path
@ -29,14 +27,13 @@ RSpec.describe 'Settings Privacy' do
.to have_content(I18n.t('privacy.title'))
.and have_content(success_message)
expect(ActivityPub::UpdateDistributionWorker)
.to have_received(:perform_async).with(user.account.id)
.to have_enqueued_sidekiq_job(user.account.id)
end
end
context 'with a failed update' do
before do
allow(UpdateAccountService).to receive(:new).and_return(failing_update_service)
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
end
it 'updates user profile information' do
@ -54,7 +51,7 @@ RSpec.describe 'Settings Privacy' do
expect(page)
.to have_content(I18n.t('privacy.title'))
expect(ActivityPub::UpdateDistributionWorker)
.to_not have_received(:perform_async)
.to_not have_enqueued_sidekiq_job(anything)
end
private

View File

@ -7,7 +7,6 @@ RSpec.describe 'Settings profile page' do
let(:account) { user.account }
before do
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
sign_in user
end
@ -24,7 +23,7 @@ RSpec.describe 'Settings profile page' do
.to change { account.reload.display_name }.to('New name')
.and(change { account.reload.avatar.instance.avatar_file_name }.from(nil).to(be_present))
expect(ActivityPub::UpdateDistributionWorker)
.to have_received(:perform_async).with(account.id)
.to have_enqueued_sidekiq_job(account.id)
end
def display_name_field