Fix submitting a status twice leading to a 500 error (#40439)

This commit is contained in:
Claire
2026-09-10 07:04:18 +00:00
committed by GitHub
parent e90160eb72
commit 4e15f3db70
2 changed files with 17 additions and 7 deletions

View File

@@ -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

View File

@@ -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