mirror of
https://github.com/discourse/discourse.git
synced 2025-03-01 16:59:22 +00:00
FIX: Prevent infinite loop of automations triggering each other (#26814)
It's currently possible to setup multiple automation rules that trigger each other resulting in an infinite loop. To prevent that, this commit adds a global "circuit breaker" that prevents all automations from triggering while an automation rule is executing. Internal topic: t/124365.
This commit is contained in:
parent
ff8e1f4ed6
commit
0e44072b2b
@ -134,11 +134,23 @@ module DiscourseAutomation
|
||||
|
||||
def trigger!(context = {})
|
||||
if enabled
|
||||
if scriptable.background && !running_in_background
|
||||
trigger_in_background!(context)
|
||||
else
|
||||
triggerable&.on_call&.call(self, serialized_fields)
|
||||
scriptable.script.call(context, serialized_fields, self)
|
||||
if active_id = DiscourseAutomation.get_active_automation
|
||||
Rails.logger.warn(<<~TEXT.strip)
|
||||
[automation] potential automations infinite loop detected: skipping automation #{self.id} because automation #{active_id} is still executing.")
|
||||
TEXT
|
||||
return
|
||||
end
|
||||
|
||||
begin
|
||||
DiscourseAutomation.set_active_automation(self.id)
|
||||
if scriptable.background && !running_in_background
|
||||
trigger_in_background!(context)
|
||||
else
|
||||
triggerable&.on_call&.call(self, serialized_fields)
|
||||
scriptable.script.call(context, serialized_fields, self)
|
||||
end
|
||||
ensure
|
||||
DiscourseAutomation.set_active_automation(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -28,6 +28,14 @@ module ::DiscourseAutomation
|
||||
|
||||
AUTO_RESPONDER_TRIGGERED_IDS = "auto_responder_triggered_ids"
|
||||
USER_GROUP_MEMBERSHIP_THROUGH_BADGE_BULK_MODIFY_START_COUNT = 1000
|
||||
|
||||
def self.set_active_automation(id)
|
||||
@active_automation_id = id
|
||||
end
|
||||
|
||||
def self.get_active_automation
|
||||
@active_automation_id
|
||||
end
|
||||
end
|
||||
|
||||
require_relative "lib/discourse_automation/engine"
|
||||
|
@ -0,0 +1,47 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "../discourse_automation_helper"
|
||||
|
||||
describe "Infinite loop protection" do
|
||||
fab!(:automation_1) do
|
||||
Fabricate(:automation, script: "auto_responder", trigger: "post_created_edited", enabled: true)
|
||||
end
|
||||
|
||||
fab!(:automation_2) do
|
||||
Fabricate(:automation, script: "auto_responder", trigger: "post_created_edited", enabled: true)
|
||||
end
|
||||
|
||||
before do
|
||||
SiteSetting.discourse_automation_enabled = true
|
||||
|
||||
automation_1.upsert_field!(
|
||||
"word_answer_list",
|
||||
"key-value",
|
||||
{ value: [{ key: "", value: "this is the reply" }].to_json },
|
||||
)
|
||||
automation_2.upsert_field!(
|
||||
"word_answer_list",
|
||||
"key-value",
|
||||
{ value: [{ key: "", value: "this is the reply" }].to_json },
|
||||
)
|
||||
|
||||
automation_1.upsert_field!(
|
||||
"answering_user",
|
||||
"user",
|
||||
{ value: Fabricate(:user).username },
|
||||
target: "script",
|
||||
)
|
||||
automation_2.upsert_field!(
|
||||
"answering_user",
|
||||
"user",
|
||||
{ value: Fabricate(:user).username },
|
||||
target: "script",
|
||||
)
|
||||
end
|
||||
|
||||
it "prevents infinite loop of 2 auto_responder automations triggering each other" do
|
||||
expect do
|
||||
PostCreator.create!(Fabricate(:user), raw: "post", title: "topic", skip_validations: true)
|
||||
end.to change { Post.count }.by(3)
|
||||
end
|
||||
end
|
@ -46,16 +46,6 @@ describe DiscourseAutomation::Automation do
|
||||
Jobs::DiscourseAutomationTrigger.jobs.size
|
||||
}.by(1)
|
||||
end
|
||||
|
||||
it "also runs the script properly" do
|
||||
Jobs.run_immediately!
|
||||
post = Fabricate(:post)
|
||||
user = post.user
|
||||
list = capture_contexts { automation.trigger!({ post: post, user: user, test: :test }) }
|
||||
expect(list[0]["post"].id).to eq(post.id)
|
||||
expect(list[0]["user"].id).to eq(user.id)
|
||||
expect(list[0]["test"]).to eq(:test)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#detach_custom_field" do
|
||||
|
Loading…
x
Reference in New Issue
Block a user