mirror of
https://github.com/mastodon/mastodon.git
synced 2025-05-11 12:11:12 +00:00
Add delay to profile updates to debounce them (#34137)
This commit is contained in:
parent
d9fb61f305
commit
6d53e8c6c5
|
@ -14,7 +14,7 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
|
||||||
@account = current_account
|
@account = current_account
|
||||||
UpdateAccountService.new.call(@account, account_params, raise_error: true)
|
UpdateAccountService.new.call(@account, account_params, raise_error: true)
|
||||||
current_user.update(user_params) if user_params
|
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
|
render json: @account, serializer: REST::CredentialAccountSerializer
|
||||||
rescue ActiveRecord::RecordInvalid => e
|
rescue ActiveRecord::RecordInvalid => e
|
||||||
render json: ValidationErrorFormatter.new(e).as_json, status: 422
|
render json: ValidationErrorFormatter.new(e).as_json, status: 422
|
||||||
|
|
|
@ -7,7 +7,7 @@ class Api::V1::Profile::AvatarsController < Api::BaseController
|
||||||
def destroy
|
def destroy
|
||||||
@account = current_account
|
@account = current_account
|
||||||
UpdateAccountService.new.call(@account, { avatar: nil }, raise_error: true)
|
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
|
render json: @account, serializer: REST::CredentialAccountSerializer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,7 @@ class Api::V1::Profile::HeadersController < Api::BaseController
|
||||||
def destroy
|
def destroy
|
||||||
@account = current_account
|
@account = current_account
|
||||||
UpdateAccountService.new.call(@account, { header: nil }, raise_error: true)
|
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
|
render json: @account, serializer: REST::CredentialAccountSerializer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ module Settings
|
||||||
def destroy
|
def destroy
|
||||||
if valid_picture?
|
if valid_picture?
|
||||||
if UpdateAccountService.new.call(@account, { @picture => nil, "#{@picture}_remote_url" => '' })
|
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
|
redirect_to settings_profile_path, notice: I18n.t('generic.changes_saved_msg'), status: 303
|
||||||
else
|
else
|
||||||
redirect_to settings_profile_path
|
redirect_to settings_profile_path
|
||||||
|
|
|
@ -8,7 +8,7 @@ class Settings::PrivacyController < Settings::BaseController
|
||||||
def update
|
def update
|
||||||
if UpdateAccountService.new.call(@account, account_params.except(:settings))
|
if UpdateAccountService.new.call(@account, account_params.except(:settings))
|
||||||
current_user.update!(settings_attributes: account_params[: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')
|
redirect_to settings_privacy_path, notice: I18n.t('generic.changes_saved_msg')
|
||||||
else
|
else
|
||||||
render :show
|
render :show
|
||||||
|
|
|
@ -9,7 +9,7 @@ class Settings::ProfilesController < Settings::BaseController
|
||||||
|
|
||||||
def update
|
def update
|
||||||
if UpdateAccountService.new.call(@account, account_params)
|
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')
|
redirect_to settings_profile_path, notice: I18n.t('generic.changes_saved_msg')
|
||||||
else
|
else
|
||||||
@account.build_fields
|
@account.build_fields
|
||||||
|
|
|
@ -8,7 +8,7 @@ class Settings::VerificationsController < Settings::BaseController
|
||||||
|
|
||||||
def update
|
def update
|
||||||
if UpdateAccountService.new.call(@account, account_params)
|
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')
|
redirect_to settings_verification_path, notice: I18n.t('generic.changes_saved_msg')
|
||||||
else
|
else
|
||||||
render :show
|
render :show
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class ActivityPub::UpdateDistributionWorker < ActivityPub::RawDistributionWorker
|
class ActivityPub::UpdateDistributionWorker < ActivityPub::RawDistributionWorker
|
||||||
|
DEBOUNCE_DELAY = 5.seconds
|
||||||
|
|
||||||
sidekiq_options queue: 'push', lock: :until_executed, lock_ttl: 1.day.to_i
|
sidekiq_options queue: 'push', lock: :until_executed, lock_ttl: 1.day.to_i
|
||||||
|
|
||||||
# Distribute an profile update to servers that might have a copy
|
# Distribute an profile update to servers that might have a copy
|
||||||
|
|
|
@ -31,7 +31,7 @@ RSpec.describe Settings::PrivacyController do
|
||||||
describe 'PUT #update' do
|
describe 'PUT #update' do
|
||||||
context 'when update succeeds' do
|
context 'when update succeeds' do
|
||||||
before do
|
before do
|
||||||
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
|
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_in)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the user profile' do
|
it 'updates the user profile' do
|
||||||
|
@ -44,14 +44,14 @@ RSpec.describe Settings::PrivacyController do
|
||||||
.to redirect_to(settings_privacy_path)
|
.to redirect_to(settings_privacy_path)
|
||||||
|
|
||||||
expect(ActivityPub::UpdateDistributionWorker)
|
expect(ActivityPub::UpdateDistributionWorker)
|
||||||
.to have_received(:perform_async).with(account.id)
|
.to have_received(:perform_in).with(anything, account.id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when update fails' do
|
context 'when update fails' do
|
||||||
before do
|
before do
|
||||||
allow(UpdateAccountService).to receive(:new).and_return(failing_update_service)
|
allow(UpdateAccountService).to receive(:new).and_return(failing_update_service)
|
||||||
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
|
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_in)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the user profile' do
|
it 'updates the user profile' do
|
||||||
|
@ -61,7 +61,7 @@ RSpec.describe Settings::PrivacyController do
|
||||||
.to render_template(:show)
|
.to render_template(:show)
|
||||||
|
|
||||||
expect(ActivityPub::UpdateDistributionWorker)
|
expect(ActivityPub::UpdateDistributionWorker)
|
||||||
.to_not have_received(:perform_async)
|
.to_not have_received(:perform_in)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -29,23 +29,23 @@ RSpec.describe Settings::ProfilesController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the user profile' do
|
it 'updates the user profile' do
|
||||||
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
|
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_in)
|
||||||
put :update, params: { account: { display_name: 'New name' } }
|
put :update, params: { account: { display_name: 'New name' } }
|
||||||
expect(account.reload.display_name).to eq 'New name'
|
expect(account.reload.display_name).to eq 'New name'
|
||||||
expect(response).to redirect_to(settings_profile_path)
|
expect(response).to redirect_to(settings_profile_path)
|
||||||
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id)
|
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_in).with(anything, account.id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'PUT #update with new profile image' do
|
describe 'PUT #update with new profile image' do
|
||||||
it 'updates profile image' do
|
it 'updates profile image' do
|
||||||
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
|
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_in)
|
||||||
expect(account.avatar.instance.avatar_file_name).to be_nil
|
expect(account.avatar.instance.avatar_file_name).to be_nil
|
||||||
|
|
||||||
put :update, params: { account: { avatar: fixture_file_upload('avatar.gif', 'image/gif') } }
|
put :update, params: { account: { avatar: fixture_file_upload('avatar.gif', 'image/gif') } }
|
||||||
expect(response).to redirect_to(settings_profile_path)
|
expect(response).to redirect_to(settings_profile_path)
|
||||||
expect(account.reload.avatar.instance.avatar_file_name).to_not be_nil
|
expect(account.reload.avatar.instance.avatar_file_name).to_not be_nil
|
||||||
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id)
|
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_in).with(anything, account.id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -53,8 +53,6 @@ RSpec.describe 'credentials API' do
|
||||||
patch '/api/v1/accounts/update_credentials', headers: headers, params: params
|
patch '/api/v1/accounts/update_credentials', headers: headers, params: params
|
||||||
end
|
end
|
||||||
|
|
||||||
before { allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async) }
|
|
||||||
|
|
||||||
let(:params) do
|
let(:params) do
|
||||||
{
|
{
|
||||||
avatar: fixture_file_upload('avatar.gif', 'image/gif'),
|
avatar: fixture_file_upload('avatar.gif', 'image/gif'),
|
||||||
|
@ -112,7 +110,7 @@ RSpec.describe 'credentials API' do
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(ActivityPub::UpdateDistributionWorker)
|
expect(ActivityPub::UpdateDistributionWorker)
|
||||||
.to have_received(:perform_async).with(user.account_id)
|
.to have_enqueued_sidekiq_job(user.account_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def expect_account_updates
|
def expect_account_updates
|
||||||
|
|
|
@ -15,10 +15,6 @@ RSpec.describe 'Deleting profile images' do
|
||||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||||
|
|
||||||
describe 'DELETE /api/v1/profile' do
|
describe 'DELETE /api/v1/profile' do
|
||||||
before do
|
|
||||||
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when deleting an avatar' do
|
context 'when deleting an avatar' do
|
||||||
context 'with wrong scope' do
|
context 'with wrong scope' do
|
||||||
before do
|
before do
|
||||||
|
@ -38,7 +34,8 @@ RSpec.describe 'Deleting profile images' do
|
||||||
account.reload
|
account.reload
|
||||||
expect(account.avatar).to_not exist
|
expect(account.avatar).to_not exist
|
||||||
expect(account.header).to 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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -61,7 +58,8 @@ RSpec.describe 'Deleting profile images' do
|
||||||
account.reload
|
account.reload
|
||||||
expect(account.avatar).to exist
|
expect(account.avatar).to exist
|
||||||
expect(account.header).to_not 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
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user