Skip to content

Commit ac7dc97

Browse files
authored
fix: don't update Slack messages if resolution note text not changed (#5126)
# What this PR does Reduces the number of `chat.update` Slack API calls when a resolution note is updated with the same text. <!-- *Note*: If you want the issue to be auto-closed once the PR is merged, change "Related to" to "Closes" in the line above. If you have more than one GitHub issue that this PR closes, be sure to preface each issue link with a [closing keyword](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/using-keywords-in-issues-and-pull-requests#linking-a-pull-request-to-an-issue). This ensures that the issue(s) are auto-closed once the PR has been merged. --> ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes.
1 parent c65a3c9 commit ac7dc97

File tree

2 files changed

+59
-17
lines changed

2 files changed

+59
-17
lines changed

engine/apps/public_api/tests/test_resolution_notes.py

+47-1
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,14 @@ def test_get_resolution_note(
106106
assert response.data == result
107107

108108

109+
@patch("apps.alerts.tasks.send_update_resolution_note_signal.send_update_resolution_note_signal.apply_async")
109110
@pytest.mark.django_db
110-
def test_create_resolution_note(make_organization_and_user_with_token, make_alert_receive_channel, make_alert_group):
111+
def test_create_resolution_note(
112+
mock_send_update_resolution_note_signal,
113+
make_organization_and_user_with_token,
114+
make_alert_receive_channel,
115+
make_alert_group,
116+
):
111117
organization, user, token = make_organization_and_user_with_token()
112118
client = APIClient()
113119

@@ -137,6 +143,8 @@ def test_create_resolution_note(make_organization_and_user_with_token, make_aler
137143
assert response.status_code == status.HTTP_201_CREATED
138144
assert response.data == result
139145

146+
mock_send_update_resolution_note_signal.assert_called_once()
147+
140148

141149
@pytest.mark.django_db
142150
def test_create_resolution_note_invalid_text(
@@ -163,8 +171,10 @@ def test_create_resolution_note_invalid_text(
163171
assert response.data["text"][0] == "This field may not be blank."
164172

165173

174+
@patch("apps.alerts.tasks.send_update_resolution_note_signal.send_update_resolution_note_signal.apply_async")
166175
@pytest.mark.django_db
167176
def test_update_resolution_note(
177+
mock_send_update_resolution_note_signal,
168178
make_organization_and_user_with_token,
169179
make_alert_receive_channel,
170180
make_alert_group,
@@ -206,6 +216,39 @@ def test_update_resolution_note(
206216
assert resolution_note.text == result["text"]
207217
assert response.data == result
208218

219+
mock_send_update_resolution_note_signal.assert_called_once()
220+
221+
222+
@patch("apps.alerts.tasks.send_update_resolution_note_signal.send_update_resolution_note_signal.apply_async")
223+
@pytest.mark.django_db
224+
def test_update_resolution_note_same_text(
225+
mock_send_update_resolution_note_signal,
226+
make_organization_and_user_with_token,
227+
make_alert_receive_channel,
228+
make_alert_group,
229+
make_resolution_note,
230+
):
231+
organization, user, token = make_organization_and_user_with_token()
232+
client = APIClient()
233+
234+
alert_receive_channel = make_alert_receive_channel(organization)
235+
alert_group = make_alert_group(alert_receive_channel)
236+
237+
resolution_note = make_resolution_note(
238+
alert_group=alert_group,
239+
source=ResolutionNote.Source.WEB,
240+
author=user,
241+
)
242+
243+
url = reverse("api-public:resolution_notes-detail", kwargs={"pk": resolution_note.public_primary_key})
244+
response = client.put(
245+
url, data={"text": resolution_note.message_text}, format="json", HTTP_AUTHORIZATION=f"{token}"
246+
)
247+
assert response.status_code == status.HTTP_200_OK
248+
249+
# update signal shouldn't be sent when text doesn't change
250+
mock_send_update_resolution_note_signal.assert_not_called()
251+
209252

210253
@pytest.mark.django_db
211254
def test_update_resolution_note_invalid_source(
@@ -242,8 +285,10 @@ def test_update_resolution_note_invalid_source(
242285
assert response.data["detail"] == "Cannot update message with this source type"
243286

244287

288+
@patch("apps.alerts.tasks.send_update_resolution_note_signal.send_update_resolution_note_signal.apply_async")
245289
@pytest.mark.django_db
246290
def test_delete_resolution_note(
291+
mock_send_update_resolution_note_signal,
247292
make_organization_and_user_with_token,
248293
make_alert_receive_channel,
249294
make_alert_group,
@@ -272,6 +317,7 @@ def test_delete_resolution_note(
272317
resolution_note.refresh_from_db()
273318

274319
assert resolution_note.deleted_at is not None
320+
mock_send_update_resolution_note_signal.assert_called_once()
275321

276322
response = client.get(url, format="json", HTTP_AUTHORIZATION=f"{token}")
277323

engine/apps/public_api/views/resolution_notes.py

+12-16
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,16 @@ def get_object(self):
5656
except ResolutionNote.DoesNotExist:
5757
raise NotFound
5858

59-
def dispatch(self, request, *args, **kwargs):
60-
result = super().dispatch(request, *args, **kwargs)
59+
def perform_create(self, serializer):
60+
super().perform_create(serializer)
61+
send_update_resolution_note_signal.apply_async((serializer.instance.alert_group.pk, serializer.instance.pk))
6162

62-
# send signal to update alert group and resolution_note
63-
method = request.method.lower()
64-
if method in ["post", "put", "patch", "delete"]:
65-
instance_id = self.kwargs.get("pk") or result.data.get("id")
66-
if instance_id:
67-
instance = ResolutionNote.objects_with_deleted.filter(public_primary_key=instance_id).first()
68-
if instance is not None:
69-
send_update_resolution_note_signal.apply_async(
70-
kwargs={
71-
"alert_group_pk": instance.alert_group.pk,
72-
"resolution_note_pk": instance.pk,
73-
}
74-
)
75-
return result
63+
def perform_update(self, serializer):
64+
is_text_updated = serializer.instance.message_text != serializer.validated_data["message_text"]
65+
super().perform_update(serializer)
66+
if is_text_updated:
67+
send_update_resolution_note_signal.apply_async((serializer.instance.alert_group.pk, serializer.instance.pk))
68+
69+
def perform_destroy(self, instance):
70+
super().perform_destroy(instance)
71+
send_update_resolution_note_signal.apply_async((instance.alert_group.pk, instance.pk))

0 commit comments

Comments
 (0)