Auto-reconnect to event stream after 20secs timeout

This commit is contained in:
Deluan 2020-11-09 15:13:32 -05:00
parent 2b1a5f579a
commit 56803d0151
7 changed files with 40 additions and 26 deletions

View File

@ -17,7 +17,7 @@ type Broker interface {
type broker struct { type broker struct {
// Events are pushed to this channel by the main events-gathering routine // Events are pushed to this channel by the main events-gathering routine
Notifier chan []byte notifier chan []byte
// New client connections // New client connections
newClients chan chan []byte newClients chan chan []byte
@ -32,7 +32,7 @@ type broker struct {
func NewBroker() Broker { func NewBroker() Broker {
// Instantiate a broker // Instantiate a broker
broker := &broker{ broker := &broker{
Notifier: make(chan []byte, 1), notifier: make(chan []byte, 1),
newClients: make(chan chan []byte), newClients: make(chan chan []byte),
closingClients: make(chan chan []byte), closingClients: make(chan chan []byte),
clients: make(map[chan []byte]bool), clients: make(map[chan []byte]bool),
@ -52,7 +52,7 @@ func (broker *broker) SendMessage(event Event) {
pkg.Name = event.EventName() pkg.Name = event.EventName()
pkg.Event = event pkg.Event = event
data, _ := json.Marshal(pkg) data, _ := json.Marshal(pkg)
broker.Notifier <- data broker.notifier <- data
} }
func (broker *broker) ServeHTTP(rw http.ResponseWriter, req *http.Request) { func (broker *broker) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
@ -119,7 +119,7 @@ func (broker *broker) listen() {
// stop sending them messages. // stop sending them messages.
delete(broker.clients, s) delete(broker.clients, s)
log.Debug("Removed client", "numClients", len(broker.clients)) log.Debug("Removed client", "numClients", len(broker.clients))
case event := <-broker.Notifier: case event := <-broker.notifier:
// We got a new event from the outside! // We got a new event from the outside!
// Send event to all connected clients // Send event to all connected clients

View File

@ -27,7 +27,7 @@ import createAdminStore from './store/createAdminStore'
import { i18nProvider } from './i18n' import { i18nProvider } from './i18n'
import config from './config' import config from './config'
import { startEventStream } from './eventStream' import { startEventStream } from './eventStream'
import { updateScanStatus } from './actions' import { processEvent } from './actions'
const history = createHashHistory() const history = createHashHistory()
if (config.gaTrackingId) { if (config.gaTrackingId) {
@ -59,7 +59,7 @@ const App = () => (
const Admin = (props) => { const Admin = (props) => {
const dispatch = useDispatch() const dispatch = useDispatch()
startEventStream((data) => dispatch(updateScanStatus(data))) startEventStream((data) => dispatch(processEvent(data)))
return ( return (
<RAAdmin <RAAdmin

View File

@ -1,12 +0,0 @@
export const ACTIVITY_SCAN_STATUS_UPD = 'ACTIVITY_SCAN_STATUS_UPD'
const actionsMap = { scanStatus: ACTIVITY_SCAN_STATUS_UPD }
export const updateScanStatus = (data) => {
let type = actionsMap[data.name]
if (!type) type = 'UNKNOWN'
return {
type,
data: data.data,
}
}

View File

@ -2,4 +2,4 @@ export * from './audioplayer'
export * from './themes' export * from './themes'
export * from './albumView' export * from './albumView'
export * from './dialogs' export * from './dialogs'
export * from './activity' export * from './serverEvents'

View File

@ -0,0 +1,12 @@
export const EVENT_SCAN_STATUS = 'ACTIVITY_SCAN_STATUS_UPD'
const actionsMap = { scanStatus: EVENT_SCAN_STATUS }
export const processEvent = (data) => {
let type = actionsMap[data.name]
if (!type) type = 'EVENT_UNKNOWN'
return {
type,
data: data.data,
}
}

View File

@ -1,9 +1,9 @@
import baseUrl from './utils/baseUrl' import baseUrl from './utils/baseUrl'
import throttle from 'lodash.throttle' import throttle from 'lodash.throttle'
// TODO https://stackoverflow.com/a/20060461
let es = null let es = null
let dispatchFunc = null let onMessageHandler = null
let timeOut = null
const getEventStream = () => { const getEventStream = () => {
if (es === null) { if (es === null) {
@ -14,17 +14,31 @@ const getEventStream = () => {
return es return es
} }
export const startEventStream = (func) => { // Reestablish the event stream after 20 secs of inactivity
const setTimeout = () => {
if (timeOut != null) {
window.clearTimeout(timeOut)
}
timeOut = window.setTimeout(() => {
es.close()
es = null
startEventStream(onMessageHandler)
}, 20000)
}
export const startEventStream = (messageHandler) => {
const es = getEventStream() const es = getEventStream()
dispatchFunc = func onMessageHandler = messageHandler
es.onmessage = throttle( es.onmessage = throttle(
(msg) => { (msg) => {
const data = JSON.parse(msg.data) const data = JSON.parse(msg.data)
if (data.name !== 'keepAlive') { if (data.name !== 'keepAlive') {
dispatchFunc(data) onMessageHandler(data)
} }
setTimeout() // Reset timeout on every received message
}, },
100, 100,
{ trailing: true } { trailing: true }
) )
setTimeout()
} }

View File

@ -1,4 +1,4 @@
import { ACTIVITY_SCAN_STATUS_UPD } from '../actions' import { EVENT_SCAN_STATUS } from '../actions'
export const activityReducer = ( export const activityReducer = (
previousState = { previousState = {
@ -8,7 +8,7 @@ export const activityReducer = (
) => { ) => {
const { type, data } = payload const { type, data } = payload
switch (type) { switch (type) {
case ACTIVITY_SCAN_STATUS_UPD: case EVENT_SCAN_STATUS:
return { ...previousState, scanStatus: data } return { ...previousState, scanStatus: data }
default: default:
return previousState return previousState