Skip to content

Commit b9ac3ba

Browse files
committed
handling ignored edit&retry
1 parent 3522fb7 commit b9ac3ba

File tree

6 files changed

+112
-35
lines changed

6 files changed

+112
-35
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<script setup lang="ts">
2+
const emit = defineEmits<{
3+
close: [];
4+
}>();
5+
6+
function closeDialog() {
7+
emit("close");
8+
}
9+
</script>
10+
11+
<template>
12+
<section name="edit_ignored_dialog">
13+
<div class="modal" style="z-index: 1050; display: block" role="dialog" aria-label="edit ignored">
14+
<div class="modal-mask">
15+
<div class="modal-dialog">
16+
<div class="modal-content">
17+
<div class="modal-header">
18+
<div class="modal-title">
19+
<h3>Edit Ignored</h3>
20+
</div>
21+
</div>
22+
<div class="modal-body">
23+
<p>This retry was ignored because another edit had already been processed.</p>
24+
</div>
25+
<div class="modal-footer">
26+
<button class="btn btn-primary" @click="closeDialog()">Ok</button>
27+
</div>
28+
</div>
29+
</div>
30+
</div>
31+
</div>
32+
</section>
33+
</template>
34+
35+
<style scoped>
36+
@import "@/components/modal.css";
37+
</style>

src/Frontend/src/components/failedmessages/EditRetryDialog.vue

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,8 @@ import { storeToRefs } from "pinia";
1010
import LoadingSpinner from "@/components/LoadingSpinner.vue";
1111
import FAIcon from "@/components/FAIcon.vue";
1212
import { faExclamationCircle, faExclamationTriangle, faUndo } from "@fortawesome/free-solid-svg-icons";
13+
import { HeaderWithEditing } from "@/resources/EditMessage";
1314
import { useDebounceFn } from "@vueuse/core";
14-
import useEnvironmentAndVersionsAutoRefresh from "@/composables/useEnvironmentAndVersionsAutoRefresh";
15-
import { useServiceControlStore } from "@/stores/ServiceControlStore";
16-
17-
interface HeaderWithEditing extends Header {
18-
isLocked: boolean;
19-
isSensitive: boolean;
20-
isMarkedAsRemoved: boolean;
21-
isChanged: boolean;
22-
}
2315
2416
const emit = defineEmits<{
2517
cancel: [];
@@ -56,9 +48,6 @@ const showCancelConfirmation = ref(false);
5648
const showEditRetryGenericError = ref(false);
5749
const messageStore = useMessageStore();
5850
const { state, headers, body, edit_and_retry_config } = storeToRefs(messageStore);
59-
const { store: environmentStore } = useEnvironmentAndVersionsAutoRefresh();
60-
const areSimpleHeadersSupported = environmentStore.serviceControlIsGreaterThan("5.2.0");
61-
const serviceControlStore = useServiceControlStore();
6251
6352
const id = computed(() => state.value.data.id ?? "");
6453
const uneditedMessageBody = computed(() => body.value.data.value ?? "");
@@ -110,24 +99,7 @@ function removeHeadersMarkedAsRemoved() {
11099
async function retryEditedMessage() {
111100
removeHeadersMarkedAsRemoved();
112101
try {
113-
const payload = {
114-
message_body: localMessage.value.messageBody,
115-
message_headers: areSimpleHeadersSupported.value
116-
? localMessage.value.headers.reduce(
117-
(result, header) => {
118-
const { key, value } = header as { key: string; value: string };
119-
result[key] = value;
120-
return result;
121-
},
122-
{} as { [key: string]: string }
123-
)
124-
: localMessage.value.headers,
125-
};
126-
const response = await serviceControlStore.postToServiceControl(`edit/${id.value}`, payload);
127-
if (!response.ok) {
128-
throw new Error(response.statusText);
129-
}
130-
102+
await messageStore.retryEditedMessage(id.value, localMessage);
131103
localMessage.value.retried = true;
132104
return emit("confirm");
133105
} catch {

src/Frontend/src/components/messages/EditAndRetryButton.vue

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,36 @@ import { computed, ref } from "vue";
55
import { useShowToast } from "@/composables/toast";
66
import { TYPE } from "vue-toastification";
77
import EditRetryDialog from "@/components/failedmessages/EditRetryDialog.vue";
8+
import EditIgnoredDialog from "@/components/failedmessages/EditIgnoredDialog.vue";
89
import { MessageStatus } from "@/resources/Message";
910
import { storeToRefs } from "pinia";
1011
import { FailedMessageStatus } from "@/resources/FailedMessage";
1112
import { faPencil } from "@fortawesome/free-solid-svg-icons";
1213
1314
const store = useMessageStore();
14-
const { state, edit_and_retry_config } = storeToRefs(store);
15+
const { state, edit_and_retry_config, editRetryResponse } = storeToRefs(store);
1516
const isConfirmDialogVisible = ref(false);
17+
const isEditIgnoredDialogVisible = ref(false);
1618
1719
const failureStatus = computed(() => state.value.data.failure_status);
1820
const isDisabled = computed(() => failureStatus.value.retried || failureStatus.value.archived || failureStatus.value.resolved);
1921
const isVisible = computed(() => edit_and_retry_config.value.enabled && state.value.data.status !== MessageStatus.Successful && state.value.data.status !== MessageStatus.ResolvedSuccessfully);
22+
23+
const handleIgnoreClose = async () => {
24+
isEditIgnoredDialogVisible.value = false;
25+
await store.pollForNextUpdate(FailedMessageStatus.Resolved);
26+
};
27+
2028
const handleConfirm = async () => {
2129
isConfirmDialogVisible.value = false;
2230
23-
const message = `Retrying the edited message ${state.value.data.id} ...`;
24-
useShowToast(TYPE.INFO, "Info", message);
25-
await store.pollForNextUpdate(FailedMessageStatus.Resolved);
31+
if (editRetryResponse.value?.edit_ignored) {
32+
isEditIgnoredDialogVisible.value = true;
33+
} else {
34+
const message = `Retrying the edited message ${state.value.data.id} ...`;
35+
useShowToast(TYPE.INFO, "Info", message);
36+
await store.pollForNextUpdate(FailedMessageStatus.Resolved);
37+
}
2638
};
2739
2840
async function openDialog() {
@@ -36,6 +48,7 @@ async function openDialog() {
3648
<ActionButton :icon="faPencil" aria-label="Edit & retry" :disabled="isDisabled" @click="openDialog">Edit & retry</ActionButton>
3749
<Teleport to="#modalDisplay">
3850
<EditRetryDialog v-if="isConfirmDialogVisible" @cancel="isConfirmDialogVisible = false" @confirm="handleConfirm"></EditRetryDialog>
51+
<EditIgnoredDialog v-if="isEditIgnoredDialogVisible" @close="handleIgnoreClose"></EditIgnoredDialog>
3952
</Teleport>
4053
</template>
4154
</template>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import type Header from "./Header";
2+
3+
export interface HeaderWithEditing extends Header {
4+
isLocked: boolean;
5+
isSensitive: boolean;
6+
isMarkedAsRemoved: boolean;
7+
isChanged: boolean;
8+
}
9+
10+
export interface EditedMessage {
11+
messageBody: string;
12+
headers: HeaderWithEditing[];
13+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default interface EditRetryResponse {
2+
edit_ignored: boolean;
3+
}

src/Frontend/src/stores/MessageStore.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { acceptHMRUpdate, defineStore, storeToRefs } from "pinia";
2-
import { computed, reactive, ref } from "vue";
2+
import { computed, reactive, Ref, ref } from "vue";
33
import Header from "@/resources/Header";
44
import type EndpointDetails from "@/resources/EndpointDetails";
55
import { FailedMessage, ExceptionDetails, FailedMessageStatus } from "@/resources/FailedMessage";
@@ -11,6 +11,9 @@ import { parse, stringify } from "lossless-json";
1111
import xmlFormat from "xml-formatter";
1212
import { DataContainer } from "./DataContainer";
1313
import { useServiceControlStore } from "./ServiceControlStore";
14+
import EditRetryResponse from "@/resources/EditRetryResponse";
15+
import { EditedMessage } from "@/resources/EditMessage";
16+
import useEnvironmentAndVersionsAutoRefresh from "@/composables/useEnvironmentAndVersionsAutoRefresh";
1417

1518
interface Model {
1619
id?: string;
@@ -62,12 +65,15 @@ export const useMessageStore = defineStore("MessageStore", () => {
6265
const headers = ref<DataContainer<Header[]>>({ data: [] });
6366
const body = ref<DataContainer<{ value?: string; content_type?: string; no_content?: boolean }>>({ data: {} });
6467
const state = reactive<DataContainer<Model>>({ data: { failure_metadata: {}, failure_status: {}, dialog_status: {}, invoked_saga: {} } });
68+
const editRetryResponse = ref<EditRetryResponse | null>(null);
6569
let bodyLoadedId = "";
6670
let conversationLoadedId = "";
6771
const conversationData = ref<DataContainer<Message[]>>({ data: [] });
6872
const editRetryStore = useEditRetryStore();
6973
const configStore = useConfigurationStore();
7074
const serviceControlStore = useServiceControlStore();
75+
const { store: environmentStore } = useEnvironmentAndVersionsAutoRefresh();
76+
const areSimpleHeadersSupported = environmentStore.serviceControlIsGreaterThan("5.2.0");
7177

7278
const { config: edit_and_retry_config } = storeToRefs(editRetryStore);
7379
const { configuration } = storeToRefs(configStore);
@@ -83,6 +89,7 @@ export const useMessageStore = defineStore("MessageStore", () => {
8389
bodyLoadedId = "";
8490
conversationLoadedId = "";
8591
conversationData.value.data = [];
92+
editRetryResponse.value = null;
8693
}
8794

8895
async function loadFailedMessage(id: string) {
@@ -261,6 +268,36 @@ export const useMessageStore = defineStore("MessageStore", () => {
261268
}
262269
}
263270

271+
async function retryEditedMessage(id: string, editedMessage: Ref<EditedMessage>) {
272+
const payload = {
273+
message_body: editedMessage.value.messageBody,
274+
message_headers: areSimpleHeadersSupported.value
275+
? editedMessage.value.headers.reduce(
276+
(result, header) => {
277+
const { key, value } = header as { key: string; value: string };
278+
result[key] = value;
279+
return result;
280+
},
281+
{} as { [key: string]: string }
282+
)
283+
: editedMessage.value.headers,
284+
};
285+
const response = await serviceControlStore.postToServiceControl(`edit/${id}`, payload);
286+
if (!response.ok) {
287+
throw new Error(response.statusText);
288+
}
289+
290+
//older versions of SC return no payload about the edit result
291+
const bodyText = await response.text();
292+
if (bodyText === "") {
293+
editRetryResponse.value = {
294+
edit_ignored: false,
295+
};
296+
} else {
297+
editRetryResponse.value = parse(bodyText) as EditRetryResponse;
298+
}
299+
}
300+
264301
async function pollForNextUpdate(status: FailedMessageStatus) {
265302
if (!state.data.id) {
266303
return;
@@ -320,6 +357,7 @@ export const useMessageStore = defineStore("MessageStore", () => {
320357
body,
321358
state,
322359
edit_and_retry_config,
360+
editRetryResponse,
323361
reset,
324362
loadMessage,
325363
loadFailedMessage,
@@ -332,6 +370,7 @@ export const useMessageStore = defineStore("MessageStore", () => {
332370
retryMessages,
333371
conversationData,
334372
pollForNextUpdate,
373+
retryEditedMessage,
335374
};
336375
});
337376

0 commit comments

Comments
 (0)