Add:Notification system queueing and queue limit #996

This commit is contained in:
advplyr 2022-09-25 10:19:44 -05:00
parent 88726bed86
commit 7aa89f16c9
3 changed files with 59 additions and 4 deletions

View File

@ -6,6 +6,7 @@
<ui-btn v-if="eventName === 'onTest' && notification.enabled" :loading="testing" small class="mr-2" @click.stop="fireTestEventAndSucceed">Fire onTest Event</ui-btn> <ui-btn v-if="eventName === 'onTest' && notification.enabled" :loading="testing" small class="mr-2" @click.stop="fireTestEventAndSucceed">Fire onTest Event</ui-btn>
<ui-btn v-if="eventName === 'onTest' && notification.enabled" :loading="testing" small class="mr-2" color="red-600" @click.stop="fireTestEventAndFail">Fire & Fail</ui-btn> <ui-btn v-if="eventName === 'onTest' && notification.enabled" :loading="testing" small class="mr-2" color="red-600" @click.stop="fireTestEventAndFail">Fire & Fail</ui-btn>
<!-- <ui-btn v-if="eventName === 'onTest' && notification.enabled" :loading="testing" small class="mr-2" @click.stop="rapidFireTestEvents">Rapid Fire</ui-btn> -->
<ui-btn v-else-if="notification.enabled" :loading="sendingTest" small class="mr-2" @click.stop="sendTestClick">Test</ui-btn> <ui-btn v-else-if="notification.enabled" :loading="sendingTest" small class="mr-2" @click.stop="sendTestClick">Test</ui-btn>
<ui-btn v-else :loading="enabling" small color="success" class="mr-2" @click="enableNotification">Enable</ui-btn> <ui-btn v-else :loading="enabling" small color="success" class="mr-2" @click="enableNotification">Enable</ui-btn>
@ -52,6 +53,7 @@ export default {
} }
}, },
methods: { methods: {
// For testing using the onTest event
fireTestEventAndFail() { fireTestEventAndFail() {
this.fireTestEvent(true) this.fireTestEvent(true)
}, },
@ -74,6 +76,19 @@ export default {
this.testing = false 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() { sendTestClick() {
const payload = { const payload = {
message: `Trigger this notification with test data?`, message: `Trigger this notification with test data?`,

View File

@ -7,7 +7,8 @@ class NotificationManager {
this.db = db this.db = db
this.emitter = emitter this.emitter = emitter
this.notificationFailedMap = {} this.sendingNotification = false
this.notificationQueue = []
} }
getData() { getData() {
@ -35,7 +36,10 @@ class NotificationManager {
} }
async triggerNotification(eventName, eventData, intentionallyFail = false) { 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) const notifications = this.db.notificationSettings.getActiveNotificationsForEvent(eventName)
for (const notification of notifications) { for (const notification of notifications) {
@ -44,7 +48,7 @@ class NotificationManager {
notification.updateNotificationFired(success) notification.updateNotificationFired(success)
if (!success) { // Failed notification 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`) Logger.error(`[NotificationManager] triggerNotification: ${notification.eventName}/${notification.id} reached max failed attempts`)
notification.enabled = false notification.enabled = false
} else { } else {
@ -55,9 +59,36 @@ class NotificationManager {
await this.db.updateEntity('settings', this.db.notificationSettings) await this.db.updateEntity('settings', this.db.notificationSettings)
this.emitter('notifications_updated', 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 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) { sendTestNotification(notification) {
const eventData = notificationData.events.find(e => e.name === notification.eventName) const eventData = notificationData.events.find(e => e.name === notification.eventName)
if (!eventData) { if (!eventData) {

View File

@ -7,6 +7,9 @@ class NotificationSettings {
this.appriseType = 'api' this.appriseType = 'api'
this.appriseApiUrl = null this.appriseApiUrl = null
this.notifications = [] this.notifications = []
this.maxFailedAttempts = 5
this.maxNotificationQueue = 20 // once reached events will be ignored
this.notificationDelay = 1000 // ms delay between firing notifications
if (settings) { if (settings) {
this.construct(settings) this.construct(settings)
@ -17,6 +20,9 @@ class NotificationSettings {
this.appriseType = settings.appriseType this.appriseType = settings.appriseType
this.appriseApiUrl = settings.appriseApiUrl || null this.appriseApiUrl = settings.appriseApiUrl || null
this.notifications = (settings.notifications || []).map(n => new Notification(n)) 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() { toJSON() {
@ -24,7 +30,10 @@ class NotificationSettings {
id: this.id, id: this.id,
appriseType: this.appriseType, appriseType: this.appriseType,
appriseApiUrl: this.appriseApiUrl, 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
} }
} }