FIX: Do not leak state between alerts with the same id

FIX: Do not leak state between alerts with the same id

The alertname should also be used as a key when matching alerts

diff --git a/app/jobs/regular/process_grouped_alerts.rb b/app/jobs/regular/process_grouped_alerts.rb
index ca37c0c..e5adbbc 100644
--- a/app/jobs/regular/process_grouped_alerts.rb
+++ b/app/jobs/regular/process_grouped_alerts.rb
@@ -57,12 +57,15 @@ module Jobs
     def update_open_alerts(receiver, active_alerts, graph_url)
       Topic.open_alerts.each do |topic|
         DistributedMutex.synchronize("prom_alert_receiver_topic_#{topic.id}") do
+          alertname = receiver["topic_map"].key(topic.id)
+          next unless alertname
+
           stored_alerts = topic.custom_fields.dig(alert_history_key, 'alerts')
           updated = false
 
           stored_alerts&.each do |stored_alert|
             if stored_alert['graph_url'].include?(graph_url) && stored_alert['status'] != 'resolved'
-              active_alert = active_alerts.find { |a| a['labels']['id'] == stored_alert['id'] }
+              active_alert = active_alerts.find { |a| a['labels']['id'] == stored_alert['id'] && a['labels']['alertname'] == alertname }
 
               if !active_alert && stored_alert["status"] != "stale" &&
                   STALE_DURATION.minute.ago > DateTime.parse(stored_alert["starts_at"])
diff --git a/spec/integration/discourse_prometheus_alert_receiver/receiver_controller_spec.rb b/spec/integration/discourse_prometheus_alert_receiver/receiver_controller_spec.rb
index 3ff803e..f0f9d27 100644
--- a/spec/integration/discourse_prometheus_alert_receiver/receiver_controller_spec.rb
+++ b/spec/integration/discourse_prometheus_alert_receiver/receiver_controller_spec.rb
@@ -474,6 +474,57 @@ RSpec.describe DiscoursePrometheusAlertReceiver::ReceiverController do
 
             expect(messages).to eq([])
           end
+
+          it "should not get confused by alerts with the same id" do
+            topic2 = Fabricate(:topic, category: category)
+            topic2.custom_fields[custom_field_key] = {
+              'alerts' => [
+                {
+                  'id' => 'somethingfunny',
+                  'starts_at' => "2018-07-24T23:25:31.363742333Z",
+                  'graph_url' => "http://supposed.to.be.a.url/graph?g0.expr=lolrus",
+                  'status' => 'firing',
+                  'datacenter' => datacenter
+                }
+              ]
+            }
+            topic2.custom_fields[
+              DiscoursePrometheusAlertReceiver::TOPIC_BASE_TITLE_CUSTOM_FIELD
+            ] = "some title"
+            topic2.save_custom_fields(true)
+
+            PluginStore.set(plugin_name, token,
+              PluginStore.get(plugin_name, token).tap do |data|
+                data["topic_map"]["OtherAlertName"] = topic2.id
+              end
+            )
+
+            # JobDown/somethingfunny should be firing
+            payload["data"].find {
+              |a| a["labels"]["id"] == "somethingfunny"
+            }["status"]["state"] = "active"
+
+            # Create new alert OtherAlertName/somethingfunny, which is silenced
+            payload["data"].append(
+              JSON.parse(payload["data"].find {
+                |a| a["labels"]["id"] == "somethingfunny"
+              }.to_json).tap { |a| a["labels"]["alertname"] = "OtherAlertName"; a["status"]["state"] = "suppressed" }
+            )
+
+            post "/prometheus/receiver/grouped/alerts/#{token}", params: payload
+
+            # First topic should be unaffected
+            expect(
+              topic.reload.custom_fields[custom_field_key]['alerts'].
+                  find { |a| a["id"] == "somethingfunny" }['status']
+            ).to eq('firing')
+
+            # Second topic should be updated
+            expect(
+              topic2.reload.custom_fields[custom_field_key]['alerts'].
+                  find { |a| a["id"] == "somethingfunny" }['status']
+            ).to eq('suppressed')
+          end
         end
 
         describe 'when payload is missing one alert' do

GitHub sha: 216cea1d