mirror of
https://github.com/axllent/mailpit.git
synced 2025-06-17 00:07:54 +02:00
Chore: Handle websocket errors caused by persistent connection failures (#319)
When either websockets do not work, or when they continually break connection (>3 / 15s), websockets will now stop reconnecting.
This commit is contained in:
@ -14,6 +14,8 @@ export default {
|
|||||||
toastMessage: false,
|
toastMessage: false,
|
||||||
reconnectRefresh: false,
|
reconnectRefresh: false,
|
||||||
socketURI: false,
|
socketURI: false,
|
||||||
|
socketLastConnection: 0, // timestamp to track reconnection times & avoid reloading mailbox on short disconnections
|
||||||
|
socketBreaks: 0, // to track sockets that continually connect & disconnect, reset every 15s
|
||||||
pauseNotifications: false, // prevent spamming
|
pauseNotifications: false, // prevent spamming
|
||||||
version: false,
|
version: false,
|
||||||
paginationDelayed: false, // for delayed pagination URL changes
|
paginationDelayed: false, // for delayed pagination URL changes
|
||||||
@ -21,14 +23,15 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
let d = document.getElementById('app')
|
const d = document.getElementById('app')
|
||||||
if (d) {
|
if (d) {
|
||||||
this.version = d.dataset.version
|
this.version = d.dataset.version
|
||||||
}
|
}
|
||||||
|
|
||||||
let proto = location.protocol == 'https:' ? 'wss' : 'ws'
|
const proto = location.protocol == 'https:' ? 'wss' : 'ws'
|
||||||
this.socketURI = proto + "://" + document.location.host + this.resolve(`/api/events`)
|
this.socketURI = proto + "://" + document.location.host + this.resolve(`/api/events`)
|
||||||
|
|
||||||
|
this.socketBreakReset()
|
||||||
this.connect()
|
this.connect()
|
||||||
|
|
||||||
mailbox.notificationsSupported = window.isSecureContext
|
mailbox.notificationsSupported = window.isSecureContext
|
||||||
@ -38,8 +41,8 @@ export default {
|
|||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
// websocket connect
|
// websocket connect
|
||||||
connect: function () {
|
connect() {
|
||||||
let ws = new WebSocket(this.socketURI)
|
const ws = new WebSocket(this.socketURI)
|
||||||
let self = this
|
let self = this
|
||||||
ws.onmessage = function (e) {
|
ws.onmessage = function (e) {
|
||||||
let response
|
let response
|
||||||
@ -103,6 +106,7 @@ export default {
|
|||||||
|
|
||||||
ws.onopen = function () {
|
ws.onopen = function () {
|
||||||
mailbox.connected = true
|
mailbox.connected = true
|
||||||
|
self.socketLastConnection = Date.now()
|
||||||
if (self.reconnectRefresh) {
|
if (self.reconnectRefresh) {
|
||||||
self.reconnectRefresh = false
|
self.reconnectRefresh = false
|
||||||
mailbox.refresh = true // trigger refresh
|
mailbox.refresh = true // trigger refresh
|
||||||
@ -111,8 +115,32 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ws.onclose = function (e) {
|
ws.onclose = function (e) {
|
||||||
|
if (self.socketLastConnection == 0) {
|
||||||
|
// connection failed immediately after connecting to Mailpit implies proxy websockets aren't configured
|
||||||
|
console.log('Unable to connect to websocket, disabling websocket support')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mailbox.connected) {
|
||||||
|
// count disconnections
|
||||||
|
self.socketBreaks++
|
||||||
|
}
|
||||||
|
|
||||||
|
// set disconnected state
|
||||||
mailbox.connected = false
|
mailbox.connected = false
|
||||||
|
|
||||||
|
if (self.socketBreaks > 3) {
|
||||||
|
// give up after > 3 successful socket connections & disconnections within a 15 second window,
|
||||||
|
// something is not working right on their end, see issue #319
|
||||||
|
console.log('Unstable websocket connection, disabling websocket support')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (Date.now() - self.socketLastConnection > 5000) {
|
||||||
|
// only refresh mailbox if the last successful connection was broken for > 5 seconds
|
||||||
self.reconnectRefresh = true
|
self.reconnectRefresh = true
|
||||||
|
} else {
|
||||||
|
self.reconnectRefresh = false
|
||||||
|
}
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
self.connect() // reconnect
|
self.connect() // reconnect
|
||||||
@ -124,9 +152,16 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
socketBreakReset() {
|
||||||
|
window.setTimeout(() => {
|
||||||
|
this.socketBreaks = 0
|
||||||
|
this.socketBreakReset()
|
||||||
|
}, 15000)
|
||||||
|
},
|
||||||
|
|
||||||
// This will only update the pagination offset at a maximum of 2x per second
|
// This will only update the pagination offset at a maximum of 2x per second
|
||||||
// when viewing the inbox on > page 1, while receiving an influx of new messages.
|
// when viewing the inbox on > page 1, while receiving an influx of new messages.
|
||||||
delayedPaginationUpdate: function () {
|
delayedPaginationUpdate() {
|
||||||
if (this.paginationDelayed) {
|
if (this.paginationDelayed) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -157,13 +192,12 @@ export default {
|
|||||||
}, 500)
|
}, 500)
|
||||||
},
|
},
|
||||||
|
|
||||||
browserNotify: function (title, message) {
|
browserNotify(title, message) {
|
||||||
if (!("Notification" in window)) {
|
if (!("Notification" in window)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Notification.permission === "granted") {
|
if (Notification.permission === "granted") {
|
||||||
let b = message.Subject
|
|
||||||
let options = {
|
let options = {
|
||||||
body: message,
|
body: message,
|
||||||
icon: this.resolve('/notification.png')
|
icon: this.resolve('/notification.png')
|
||||||
@ -172,7 +206,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setMessageToast: function (m) {
|
setMessageToast(m) {
|
||||||
// don't display if browser notifications are enabled, or a toast is already displayed
|
// don't display if browser notifications are enabled, or a toast is already displayed
|
||||||
if (mailbox.notificationsEnabled || this.toastMessage) {
|
if (mailbox.notificationsEnabled || this.toastMessage) {
|
||||||
return
|
return
|
||||||
@ -181,7 +215,7 @@ export default {
|
|||||||
this.toastMessage = m
|
this.toastMessage = m
|
||||||
|
|
||||||
let self = this
|
let self = this
|
||||||
let el = document.getElementById('messageToast')
|
const el = document.getElementById('messageToast')
|
||||||
if (el) {
|
if (el) {
|
||||||
el.addEventListener('hidden.bs.toast', () => {
|
el.addEventListener('hidden.bs.toast', () => {
|
||||||
self.toastMessage = false
|
self.toastMessage = false
|
||||||
@ -191,8 +225,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
closeToast: function () {
|
closeToast() {
|
||||||
let el = document.getElementById('messageToast')
|
const el = document.getElementById('messageToast')
|
||||||
if (el) {
|
if (el) {
|
||||||
Toast.getOrCreateInstance(el).hide()
|
Toast.getOrCreateInstance(el).hide()
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user