FIX: Do not call :post_edited webhook twice when editing OP (#13112)

When editing the first post for the topic we do two AJAX requests
to two separate controllers in this order:

PUT /t/topic-name
PUT /posts/2489523

This causes two post revisor calls, which end up triggering the
:post_edited DiscourseEvent twice. This is then picked up and sent
as a WebHook event twice. However we do not need to send a :post_edited
webhook event if the first post is being edited and topic_changed is
true from the :post_edited DiscourseEvent, because a second event will
shortly come through for just the post.

See https://meta.discourse.org/t/post-webhook-fires-two-times-on-post-edited-for-first-post-in-a-topic/162408

Continued on from https://github.com/discourse/discourse/pull/10590
This commit is contained in:
Martin Brennan
2021-05-24 09:10:22 +10:00
committed by GitHub
parent a5dd24c445
commit 292017dd25
4 changed files with 44 additions and 4 deletions

View File

@@ -197,7 +197,8 @@ describe WebHook do
expect do
PostRevisor.new(post, post.topic).revise!(
post.user,
category_id: category.id,
{ category_id: category.id },
{ skip_validations: true },
)
end.to change { Jobs::EmitWebHookEvent.jobs.length }.by(1)

View File

@@ -1268,12 +1268,44 @@ RSpec.describe TopicsController do
topic.reload
expect(topic.title).to eq('This is a new title for the topic')
# emits a topic_edited event but not a post_edited web hook event
expect(Jobs::EmitWebHookEvent.jobs.length).to eq(1)
job_args = Jobs::EmitWebHookEvent.jobs[0]["args"].first
expect(job_args["event_name"]).to eq("topic_edited")
payload = JSON.parse(job_args["payload"])
expect(payload["title"]).to eq('This is a new title for the topic')
end
it 'allows a change of then updating the OP' do
topic.update(user: user)
topic.first_post.update(user: user)
put "/t/#{topic.slug}/#{topic.id}.json", params: {
title: 'This is a new title for the topic'
}
topic.reload
expect(topic.title).to eq('This is a new title for the topic')
update_params = {
post: { raw: 'edited body', edit_reason: 'typo' },
}
put "/posts/#{topic.first_post.id}.json", params: update_params
# emits a topic_edited event and a post_edited web hook event
expect(Jobs::EmitWebHookEvent.jobs.length).to eq(2)
job_args = Jobs::EmitWebHookEvent.jobs[0]["args"].first
expect(job_args["event_name"]).to eq("topic_edited")
payload = JSON.parse(job_args["payload"])
expect(payload["title"]).to eq('This is a new title for the topic')
job_args = Jobs::EmitWebHookEvent.jobs[1]["args"].first
expect(job_args["event_name"]).to eq("post_edited")
payload = JSON.parse(job_args["payload"])
expect(payload["topic_title"]).to eq('This is a new title for the topic')
expect(payload["raw"]).to eq("edited body")
end
it "returns errors with invalid titles" do