mirror of
https://github.com/navidrome/navidrome.git
synced 2025-08-10 00:52:20 +00:00
Some checks failed
Pipeline: Test, Lint, Build / Get version info (push) Has been cancelled
Pipeline: Test, Lint, Build / Lint Go code (push) Has been cancelled
Pipeline: Test, Lint, Build / Test Go code (push) Has been cancelled
Pipeline: Test, Lint, Build / Test JS code (push) Has been cancelled
Pipeline: Test, Lint, Build / Lint i18n files (push) Has been cancelled
Pipeline: Test, Lint, Build / Check Docker configuration (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (darwin/amd64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (darwin/arm64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/386) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/amd64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm/v5) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm/v6) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm/v7) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (windows/386) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (windows/amd64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Push Docker manifest (push) Has been cancelled
Pipeline: Test, Lint, Build / Build Windows installers (push) Has been cancelled
Pipeline: Test, Lint, Build / Package/Release (push) Has been cancelled
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Has been cancelled
Introduced a new event, EVENT_STREAM_RECONNECTED, to track the last timestamp of stream reconnections. This change updates the activity reducer to handle the new event and modifies the NowPlayingPanel to refresh data based on server and stream status. Signed-off-by: Deluan <deluan@navidrome.org>
115 lines
3.3 KiB
JavaScript
115 lines
3.3 KiB
JavaScript
import { baseUrl } from './utils'
|
|
import throttle from 'lodash.throttle'
|
|
import { processEvent, serverDown, streamReconnected } from './actions'
|
|
import { REST_URL } from './consts'
|
|
import config from './config'
|
|
|
|
const newEventStream = async () => {
|
|
let url = baseUrl(`${REST_URL}/events`)
|
|
if (localStorage.getItem('token')) {
|
|
url = url + `?jwt=${localStorage.getItem('token')}`
|
|
}
|
|
return new EventSource(url)
|
|
}
|
|
|
|
let eventStream
|
|
let reconnectTimer
|
|
const RECONNECT_DELAY = 5000
|
|
|
|
const setupHandlers = (stream, dispatchFn) => {
|
|
stream.addEventListener('serverStart', eventHandler(dispatchFn))
|
|
stream.addEventListener('scanStatus', throttledEventHandler(dispatchFn))
|
|
stream.addEventListener('refreshResource', eventHandler(dispatchFn))
|
|
if (config.enableNowPlaying) {
|
|
stream.addEventListener('nowPlayingCount', eventHandler(dispatchFn))
|
|
}
|
|
stream.addEventListener('keepAlive', eventHandler(dispatchFn))
|
|
stream.onerror = (e) => {
|
|
// eslint-disable-next-line no-console
|
|
console.log('EventStream error', e)
|
|
dispatchFn(serverDown())
|
|
if (stream) stream.close()
|
|
scheduleReconnect(dispatchFn)
|
|
}
|
|
}
|
|
|
|
const scheduleReconnect = (dispatchFn) => {
|
|
if (!reconnectTimer) {
|
|
reconnectTimer = setTimeout(() => {
|
|
reconnectTimer = null
|
|
connect(dispatchFn)
|
|
}, RECONNECT_DELAY)
|
|
}
|
|
}
|
|
|
|
const connect = async (dispatchFn) => {
|
|
try {
|
|
const stream = await newEventStream()
|
|
eventStream = stream
|
|
setupHandlers(stream, dispatchFn)
|
|
// Dispatch reconnection event to refresh critical data
|
|
dispatchFn(streamReconnected())
|
|
return stream
|
|
} catch (e) {
|
|
// eslint-disable-next-line no-console
|
|
console.log(`Error connecting to server:`, e)
|
|
scheduleReconnect(dispatchFn)
|
|
}
|
|
}
|
|
|
|
const eventHandler = (dispatchFn) => (event) => {
|
|
const data = JSON.parse(event.data)
|
|
if (event.type !== 'keepAlive') {
|
|
dispatchFn(processEvent(event.type, data))
|
|
}
|
|
}
|
|
|
|
const throttledEventHandler = (dispatchFn) =>
|
|
throttle(eventHandler(dispatchFn), 100, { trailing: true })
|
|
|
|
const startEventStreamLegacy = async (dispatchFn) => {
|
|
return newEventStream()
|
|
.then((newStream) => {
|
|
newStream.addEventListener('serverStart', eventHandler(dispatchFn))
|
|
newStream.addEventListener(
|
|
'scanStatus',
|
|
throttledEventHandler(dispatchFn),
|
|
)
|
|
newStream.addEventListener('refreshResource', eventHandler(dispatchFn))
|
|
if (config.enableNowPlaying) {
|
|
newStream.addEventListener('nowPlayingCount', eventHandler(dispatchFn))
|
|
}
|
|
newStream.addEventListener('keepAlive', eventHandler(dispatchFn))
|
|
newStream.onerror = (e) => {
|
|
// eslint-disable-next-line no-console
|
|
console.log('EventStream error', e)
|
|
dispatchFn(serverDown())
|
|
}
|
|
return newStream
|
|
})
|
|
.catch((e) => {
|
|
// eslint-disable-next-line no-console
|
|
console.log(`Error connecting to server:`, e)
|
|
})
|
|
}
|
|
|
|
const startEventStreamNew = async (dispatchFn) => {
|
|
if (eventStream) {
|
|
eventStream.close()
|
|
eventStream = null
|
|
}
|
|
return connect(dispatchFn)
|
|
}
|
|
|
|
const startEventStream = async (dispatchFn) => {
|
|
if (!localStorage.getItem('is-authenticated')) {
|
|
return Promise.resolve()
|
|
}
|
|
if (config.devNewEventStream) {
|
|
return startEventStreamNew(dispatchFn)
|
|
}
|
|
return startEventStreamLegacy(dispatchFn)
|
|
}
|
|
|
|
export { startEventStream }
|