From dea4d47602d0c61fd6930049a022d68e84d9d96d Mon Sep 17 00:00:00 2001 From: Tanmay Deep Sharma Date: Wed, 15 Jul 2026 13:27:43 +0530 Subject: [PATCH] test(automations): sub-second awaiting-agent keys and stale processing discard --- .../automation_rule_pending_execution_spec.rb | 15 ++++++++++++--- spec/models/automation_rule_spec.rb | 6 ++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/spec/models/automation_rule_pending_execution_spec.rb b/spec/models/automation_rule_pending_execution_spec.rb index 5f9fb153f..31dd2e642 100644 --- a/spec/models/automation_rule_pending_execution_spec.rb +++ b/spec/models/automation_rule_pending_execution_spec.rb @@ -18,9 +18,18 @@ RSpec.describe AutomationRulePendingExecution do expect(described_class.episode_key_for(conversation.reload, nil)).to eq("status:#{conversation.created_at.to_f}") end - it 'derives awaiting_agent episodes from waiting_since for incoming messages' do + it 'derives awaiting_agent episodes from waiting_since (sub-second) for incoming messages' do message = create(:message, conversation: conversation, account: account, message_type: :incoming) - expect(described_class.episode_key_for(conversation.reload, message)).to eq("awaiting_agent:#{conversation.waiting_since.to_i}") + expect(described_class.episode_key_for(conversation.reload, message)).to eq("awaiting_agent:#{conversation.waiting_since.to_f}") + end + + it 'distinguishes two waiting periods that fall within the same second' do + message = create(:message, conversation: conversation, account: account, message_type: :incoming) + first_key = described_class.episode_key_for(conversation.reload, message) + + # Agent replies then customer re-waits within the same second: keys must differ. + conversation.update!(waiting_since: conversation.waiting_since + 0.4) + expect(described_class.episode_key_for(conversation.reload, message)).not_to eq(first_key) end it 'arms an awaiting_agent episode from the message created_at when waiting_since is not yet written' do @@ -31,7 +40,7 @@ RSpec.describe AutomationRulePendingExecution do # Once waiting_since settles to the message's created_at, the strict fire-time key matches. conversation.update!(waiting_since: message.created_at) - expect(armed_key).to eq("awaiting_agent:#{message.created_at.to_i}") + expect(armed_key).to eq("awaiting_agent:#{message.created_at.to_f}") expect(armed_key).to eq(described_class.episode_key_for(conversation.reload, message)) end diff --git a/spec/models/automation_rule_spec.rb b/spec/models/automation_rule_spec.rb index 91bf91df8..5e12be475 100644 --- a/spec/models/automation_rule_spec.rb +++ b/spec/models/automation_rule_spec.rb @@ -219,6 +219,12 @@ RSpec.describe AutomationRule do expect(rule.pending_executions.pending).to be_empty end + it 'discards a stale processing row that the sweep would otherwise reclaim' do + rule.pending_executions.first.update!(status: :processing) + rule.update!(actions: [{ 'action_name' => 'add_label', 'action_params' => ['urgent'] }]) + expect(rule.pending_executions.armed).to be_empty + end + it 'frees the episode slot so the new definition re-arms for the same episode' do rule.update!(actions: [{ 'action_name' => 'add_label', 'action_params' => ['urgent'] }]) AutomationRulePendingExecution.schedule(rule: rule, conversation: conversation)