diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb index 788f79535e6..239270f6e0c 100644 --- a/app/services/post_status_service.rb +++ b/app/services/post_status_service.rb @@ -20,6 +20,15 @@ class PostStatusService < BaseService end end + class IdempotencyError < StandardError + attr_reader :status + + def initialize(status) + super() + @status = status + end + end + # Post a text status update, fetch and notify remote users mentioned # @param [Account] account Account from which to post # @param [Hash] options @@ -46,9 +55,10 @@ class PostStatusService < BaseService @in_reply_to = @options[:thread] @quoted_status = @options[:quoted_status] + preprocess_attributes! + with_idempotency do validate_media! - preprocess_attributes! if scheduled? schedule_status! @@ -63,7 +73,7 @@ class PostStatusService < BaseService end @status - rescue Antispam::SilentlyDrop => e + rescue Antispam::SilentlyDrop, IdempotencyError => e e.status end @@ -237,7 +247,7 @@ class PostStatusService < BaseService return yield unless idempotency_given? with_redis_lock("idempotency:lock:status:#{@account.id}:#{@options[:idempotency]}") do - return idempotency_duplicate if idempotency_duplicate? + raise IdempotencyError, idempotency_duplicate if idempotency_duplicate? yield diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb index 66ef93f8079..052dc456a54 100644 --- a/spec/services/post_status_service_spec.rb +++ b/spec/services/post_status_service_spec.rb @@ -57,8 +57,8 @@ RSpec.describe PostStatusService do it 'returns existing status when used twice with idempotency key' do account = Fabricate(:account) - status1 = subject.call(account, text: 'test', idempotency: 'meepmeep', scheduled_at: future) - status2 = subject.call(account, text: 'test', idempotency: 'meepmeep', scheduled_at: future) + status1 = described_class.new.call(account, text: 'test', idempotency: 'meepmeep', scheduled_at: future) + status2 = described_class.new.call(account, text: 'test', idempotency: 'meepmeep', scheduled_at: future) expect(status2.id).to eq status1.id end @@ -341,8 +341,8 @@ RSpec.describe PostStatusService do it 'returns existing status when used twice with idempotency key' do account = Fabricate(:account) - status1 = subject.call(account, text: 'test', idempotency: 'meepmeep') - status2 = subject.call(account, text: 'test', idempotency: 'meepmeep') + status1 = described_class.new.call(account, text: 'test', idempotency: 'meepmeep') + status2 = described_class.new.call(account, text: 'test', idempotency: 'meepmeep') expect(status2.id).to eq status1.id end