diff --git a/client/components/cards/NotificationCard.vue b/client/components/cards/NotificationCard.vue
index 7f74239e..95ba4852 100644
--- a/client/components/cards/NotificationCard.vue
+++ b/client/components/cards/NotificationCard.vue
@@ -6,6 +6,7 @@
Fire onTest Event
Fire & Fail
+
Test
Enable
@@ -52,6 +53,7 @@ export default {
}
},
methods: {
+ // For testing using the onTest event
fireTestEventAndFail() {
this.fireTestEvent(true)
},
@@ -74,6 +76,19 @@ export default {
this.testing = false
})
},
+ rapidFireTestEvents() {
+ this.testing = true
+ var numFired = 0
+ var interval = setInterval(() => {
+ this.fireTestEvent()
+ numFired++
+ if (numFired > 25) {
+ this.testing = false
+ clearInterval(interval)
+ }
+ }, 100)
+ },
+ // End testing functions
sendTestClick() {
const payload = {
message: `Trigger this notification with test data?`,
diff --git a/server/managers/NotificationManager.js b/server/managers/NotificationManager.js
index 60c2599c..cf7a6042 100644
--- a/server/managers/NotificationManager.js
+++ b/server/managers/NotificationManager.js
@@ -7,7 +7,8 @@ class NotificationManager {
this.db = db
this.emitter = emitter
- this.notificationFailedMap = {}
+ this.sendingNotification = false
+ this.notificationQueue = []
}
getData() {
@@ -35,7 +36,10 @@ class NotificationManager {
}
async triggerNotification(eventName, eventData, intentionallyFail = false) {
- if (!this.db.notificationSettings.isUseable) return false
+ if (!this.db.notificationSettings.isUseable) return
+
+ // Will queue the notification if sendingNotification and queue is not full
+ if (!this.checkTriggerNotification(eventName, eventData)) return
const notifications = this.db.notificationSettings.getActiveNotificationsForEvent(eventName)
for (const notification of notifications) {
@@ -44,7 +48,7 @@ class NotificationManager {
notification.updateNotificationFired(success)
if (!success) { // Failed notification
- if (notification.numConsecutiveFailedAttempts > 2) {
+ if (notification.numConsecutiveFailedAttempts >= this.db.notificationSettings.maxFailedAttempts) {
Logger.error(`[NotificationManager] triggerNotification: ${notification.eventName}/${notification.id} reached max failed attempts`)
notification.enabled = false
} else {
@@ -55,9 +59,36 @@ class NotificationManager {
await this.db.updateEntity('settings', this.db.notificationSettings)
this.emitter('notifications_updated', this.db.notificationSettings)
+
+ this.notificationFinished()
+ }
+
+ // Return TRUE if notification should be triggered now
+ checkTriggerNotification(eventName, eventData) {
+ if (this.sendingNotification) {
+ if (this.notificationQueue.length >= this.db.notificationSettings.maxNotificationQueue) {
+ Logger.warn(`[NotificationManager] Notification queue is full - ignoring event ${eventName}`)
+ } else {
+ Logger.debug(`[NotificationManager] Queueing notification ${eventName} (Queue size: ${this.notificationQueue.length})`)
+ this.notificationQueue.push({ eventName, eventData })
+ }
+ return false
+ }
+ this.sendingNotification = true
return true
}
+ notificationFinished() {
+ // Delay between events then run next notification in queue
+ setTimeout(() => {
+ this.sendingNotification = false
+ if (this.notificationQueue.length) { // Send next notification in queue
+ const nextNotificationEvent = this.notificationQueue.shift()
+ this.triggerNotification(nextNotificationEvent.eventName, nextNotificationEvent.eventData)
+ }
+ }, this.db.notificationSettings.notificationDelay)
+ }
+
sendTestNotification(notification) {
const eventData = notificationData.events.find(e => e.name === notification.eventName)
if (!eventData) {
diff --git a/server/objects/settings/NotificationSettings.js b/server/objects/settings/NotificationSettings.js
index 27bb1180..838256f6 100644
--- a/server/objects/settings/NotificationSettings.js
+++ b/server/objects/settings/NotificationSettings.js
@@ -7,6 +7,9 @@ class NotificationSettings {
this.appriseType = 'api'
this.appriseApiUrl = null
this.notifications = []
+ this.maxFailedAttempts = 5
+ this.maxNotificationQueue = 20 // once reached events will be ignored
+ this.notificationDelay = 1000 // ms delay between firing notifications
if (settings) {
this.construct(settings)
@@ -17,6 +20,9 @@ class NotificationSettings {
this.appriseType = settings.appriseType
this.appriseApiUrl = settings.appriseApiUrl || null
this.notifications = (settings.notifications || []).map(n => new Notification(n))
+ this.maxFailedAttempts = settings.maxFailedAttempts || 5
+ this.maxNotificationQueue = settings.maxNotificationQueue || 20
+ this.notificationDelay = settings.notificationDelay || 1000
}
toJSON() {
@@ -24,7 +30,10 @@ class NotificationSettings {
id: this.id,
appriseType: this.appriseType,
appriseApiUrl: this.appriseApiUrl,
- notifications: this.notifications.map(n => n.toJSON())
+ notifications: this.notifications.map(n => n.toJSON()),
+ maxFailedAttempts: this.maxFailedAttempts,
+ maxNotificationQueue: this.maxNotificationQueue,
+ notificationDelay: this.notificationDelay
}
}