From cd49700d3fc9a508a1e72d457e011eca4c18bf84 Mon Sep 17 00:00:00 2001 From: Max Michels <6703026+maxmichels@users.noreply.github.com> Date: Fri, 24 Oct 2025 21:50:25 +0200 Subject: [PATCH] Adding retries to Google Chat Notifications #6242 (#6245) Co-authored-by: Frank Elsinga --- server/notification-providers/google-chat.js | 27 ++++++++++++++++++-- src/components/notifications/GoogleChat.vue | 14 ++++++++++ src/lang/en.json | 4 ++- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/server/notification-providers/google-chat.js b/server/notification-providers/google-chat.js index 1e2eb3507..2557a142c 100644 --- a/server/notification-providers/google-chat.js +++ b/server/notification-providers/google-chat.js @@ -12,6 +12,29 @@ class GoogleChat extends NotificationProvider { async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { const okMsg = "Sent Successfully."; + // If Google Chat Webhook rate limit is reached, retry to configured max retries defaults to 3, delay between 60-180 seconds + const post = async (url, data, config) => { + let retries = notification.googleChatMaxRetries || 1; // Default to 1 retries + retries = (retries > 10) ? 10 : retries; // Enforce maximum retries in backend + while (retries > 0) { + try { + await axios.post(url, data, config); + return; + } catch (error) { + if (error.response && error.response.status === 429) { + retries--; + if (retries === 0) { + throw error; + } + const delay = 60000 + Math.random() * 120000; + await new Promise(resolve => setTimeout(resolve, delay)); + } else { + throw error; + } + } + } + }; + try { let config = this.getAxiosConfigWithProxy({}); // Google Chat message formatting: https://developers.google.com/chat/api/guides/message-formats/basic @@ -24,7 +47,7 @@ class GoogleChat extends NotificationProvider { heartbeatJSON ); const data = { "text": renderedText }; - await axios.post(notification.googleChatWebhookURL, data, config); + await post(notification.googleChatWebhookURL, data, config); return okMsg; } @@ -96,7 +119,7 @@ class GoogleChat extends NotificationProvider { ], }; - await axios.post(notification.googleChatWebhookURL, data, config); + await post(notification.googleChatWebhookURL, data, config); return okMsg; } catch (error) { this.throwGeneralAxiosError(error); diff --git a/src/components/notifications/GoogleChat.vue b/src/components/notifications/GoogleChat.vue index 7b595ed59..90424cb2c 100644 --- a/src/components/notifications/GoogleChat.vue +++ b/src/components/notifications/GoogleChat.vue @@ -11,6 +11,14 @@ +
+ + +
+ {{ $t("Number of retry attempts if webhook fails") }} +
+
+
@@ -45,5 +53,11 @@ export default { ]); } }, + mounted() { + // Initialize default if needed + if (!this.$parent.notification.googleChatMaxRetries) { + this.$parent.notification.googleChatMaxRetries ||= 1; + } + }, }; diff --git a/src/lang/en.json b/src/lang/en.json index f3faaa8dc..190154331 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -1170,5 +1170,7 @@ "Bot secret": "Bot secret", "Send UP silently": "Send UP silently", "Send DOWN silently": "Send DOWN silently", - "Installing a Nextcloud Talk bot requires administrative access to the server.": "Installing a Nextcloud Talk bot requires administrative access to the server." + "Installing a Nextcloud Talk bot requires administrative access to the server.": "Installing a Nextcloud Talk bot requires administrative access to the server.", + "Number of retry attempts if webhook fails": "Number of retry attempts (every 60-180 seconds) if the webhook fails.", + "Maximum Retries": "Maximum Retries" }