Updated streaming and improved error-handling, some more refactoring to api

This commit is contained in:
Henry Jameson 2019-12-08 16:05:41 +02:00
parent 172ebaf4e6
commit ff95d865d2
7 changed files with 84 additions and 40 deletions

View File

@ -10,7 +10,7 @@ const PublicAndExternalTimeline = {
this.$store.dispatch('startFetchingTimeline', { timeline: 'publicAndExternal' }) this.$store.dispatch('startFetchingTimeline', { timeline: 'publicAndExternal' })
}, },
destroyed () { destroyed () {
this.$store.dispatch('stopFetching', 'publicAndExternal') this.$store.dispatch('stopFetchingTimeline', 'publicAndExternal')
} }
} }

View File

@ -10,7 +10,7 @@ const PublicTimeline = {
this.$store.dispatch('startFetchingTimeline', { timeline: 'public' }) this.$store.dispatch('startFetchingTimeline', { timeline: 'public' })
}, },
destroyed () { destroyed () {
this.$store.dispatch('stopFetching', 'public') this.$store.dispatch('stopFetchingTimeline', 'public')
} }
} }

View File

@ -19,7 +19,7 @@ const TagTimeline = {
} }
}, },
destroyed () { destroyed () {
this.$store.dispatch('stopFetching', 'tag') this.$store.dispatch('stopFetchingTimeline', 'tag')
} }
} }

View File

@ -112,9 +112,9 @@ const UserProfile = {
} }
}, },
stopFetching () { stopFetching () {
this.$store.dispatch('stopFetching', 'user') this.$store.dispatch('stopFetchingTimeline', 'user')
this.$store.dispatch('stopFetching', 'favorites') this.$store.dispatch('stopFetchingTimeline', 'favorites')
this.$store.dispatch('stopFetching', 'media') this.$store.dispatch('stopFetchingTimeline', 'media')
}, },
switchUser (userNameOrId) { switchUser (userNameOrId) {
this.stopFetching() this.stopFetching()

View File

@ -6,7 +6,7 @@ const api = {
backendInteractor: backendInteractorService(), backendInteractor: backendInteractorService(),
fetchers: {}, fetchers: {},
socket: null, socket: null,
mastoSocket: null, mastoUserSocket: null,
followRequests: [] followRequests: []
}, },
mutations: { mutations: {
@ -16,7 +16,8 @@ const api = {
addFetcher (state, { fetcherName, fetcher }) { addFetcher (state, { fetcherName, fetcher }) {
state.fetchers[fetcherName] = fetcher state.fetchers[fetcherName] = fetcher
}, },
removeFetcher (state, { fetcherName }) { removeFetcher (state, { fetcherName, fetcher }) {
window.clearInterval(fetcher)
delete state.fetchers[fetcherName] delete state.fetchers[fetcherName]
}, },
setWsToken (state, token) { setWsToken (state, token) {
@ -30,13 +31,14 @@ const api = {
} }
}, },
actions: { actions: {
startMastoSocket (store) { // MastoAPI 'User' sockets
startMastoUserSocket (store) {
const { state, dispatch } = store const { state, dispatch } = store
state.mastoSocket = state.backendInteractor state.mastoUserSocket = state.backendInteractor
.startUserSocket({ .startUserSocket({
store, store,
onMessage: (message) => { onMessage: (message) => {
if (!message) return if (!message) return // pings
if (message.event === 'notification') { if (message.event === 'notification') {
dispatch('addNewNotifications', { dispatch('addNewNotifications', {
notifications: [message.notification], notifications: [message.notification],
@ -52,41 +54,86 @@ const api = {
} }
} }
}) })
state.mastoSocket.addEventListener('error', error => { state.mastoUserSocket.addEventListener('error', error => {
console.error('Error with MastoAPI websocket:', error) console.error('Error in MastoAPI websocket:', error)
dispatch('startFetchingTimeline', { timeline: 'friends' }) })
dispatch('startFetchingNotifications') state.mastoUserSocket.addEventListener('close', closeEvent => {
const ignoreCodes = new Set([
1000, // Normal (intended) closure
1001 // Going away
])
const { code } = closeEvent
console.debug('Socket closure event:', closeEvent)
if (ignoreCodes.has(code)) {
console.debug(`Not restarting socket becasue of closure code ${code} is in ignore list`)
} else {
console.warn(`MastoAPI websocket disconnected, restarting. CloseEvent code: ${code}`)
dispatch('startFetchingTimeline', { timeline: 'friends' })
dispatch('startFetchingNotifications')
dispatch('restartMastoUserSocket')
}
}) })
}, },
startFetchingTimeline (store, { timeline = 'friends', tag = false, userId = false }) { restartMastoUserSocket ({ dispatch }) {
// Don't start fetching if we already are. // This basically starts MastoAPI user socket and stops conventional
// fetchers when connection reestablished
dispatch('startMastoUserSocket').then(() => {
dispatch('stopFetchingTimeline', { timeline: 'friends' })
dispatch('stopFetchingNotifications')
})
},
// Timelines
startFetchingTimeline (store, {
timeline = 'friends',
tag = false,
userId = false
}) {
if (store.state.fetchers[timeline]) return if (store.state.fetchers[timeline]) return
const fetcher = store.state.backendInteractor.startFetchingTimeline({ timeline, store, userId, tag }) const fetcher = store.state.backendInteractor.startFetchingTimeline({
timeline, store, userId, tag
})
store.commit('addFetcher', { fetcherName: timeline, fetcher }) store.commit('addFetcher', { fetcherName: timeline, fetcher })
}, },
startFetchingNotifications (store) { stopFetchingTimeline (store, timeline) {
// Don't start fetching if we already are. const fetcher = store.state.fetchers[timeline]
if (store.state.fetchers['notifications']) return if (!fetcher) return
store.commit('removeFetcher', { fetcherName: timeline, fetcher })
},
// Notifications
startFetchingNotifications (store) {
if (store.state.fetchers.notifications) return
const fetcher = store.state.backendInteractor.startFetchingNotifications({ store }) const fetcher = store.state.backendInteractor.startFetchingNotifications({ store })
store.commit('addFetcher', { fetcherName: 'notifications', fetcher }) store.commit('addFetcher', { fetcherName: 'notifications', fetcher })
}, },
stopFetchingNotifications (store) {
const fetcher = store.state.fetchers.notifications
if (!fetcher) return
store.commit('removeFetcher', { fetcherName: 'notifications', fetcher })
},
fetchAndUpdateNotifications (store) { fetchAndUpdateNotifications (store) {
store.state.backendInteractor.fetchAndUpdateNotifications({ store }) store.state.backendInteractor.fetchAndUpdateNotifications({ store })
}, },
startFetchingFollowRequest (store) {
// Don't start fetching if we already are.
if (store.state.fetchers['followRequest']) return
const fetcher = store.state.backendInteractor.startFetchingFollowRequest({ store }) // Follow requests
store.commit('addFetcher', { fetcherName: 'followRequest', fetcher }) startFetchingFollowRequests (store) {
if (store.state.fetchers['followRequests']) return
const fetcher = store.state.backendInteractor.startFetchingFollowRequests({ store })
store.commit('addFetcher', { fetcherName: 'followRequests', fetcher })
}, },
stopFetching (store, fetcherName) { stopFetchingFollowRequests (store) {
const fetcher = store.state.fetchers[fetcherName] const fetcher = store.state.fetchers.followRequests
window.clearInterval(fetcher) if (!fetcher) return
store.commit('removeFetcher', { fetcherName }) store.commit('removeFetcher', { fetcherName: 'followRequests', fetcher })
}, },
removeFollowRequest (store, request) {
let requests = store.state.followRequests.filter((it) => it !== request)
store.commit('setFollowRequests', requests)
},
// Pleroma websocket
setWsToken (store, token) { setWsToken (store, token) {
store.commit('setWsToken', token) store.commit('setWsToken', token)
}, },
@ -104,10 +151,6 @@ const api = {
disconnectFromSocket ({ commit, state }) { disconnectFromSocket ({ commit, state }) {
state.socket && state.socket.disconnect() state.socket && state.socket.disconnect()
commit('setSocket', null) commit('setSocket', null)
},
removeFollowRequest (store, request) {
let requests = store.state.followRequests.filter((it) => it !== request)
store.commit('setFollowRequests', requests)
} }
} }
} }

View File

@ -431,10 +431,10 @@ const users = {
store.commit('clearCurrentUser') store.commit('clearCurrentUser')
store.dispatch('disconnectFromSocket') store.dispatch('disconnectFromSocket')
store.commit('clearToken') store.commit('clearToken')
store.dispatch('stopFetching', 'friends') store.dispatch('stopFetchingTimeline', 'friends')
store.commit('setBackendInteractor', backendInteractorService(store.getters.getToken())) store.commit('setBackendInteractor', backendInteractorService(store.getters.getToken()))
store.dispatch('stopFetching', 'notifications') store.dispatch('stopFetchingNotifications')
store.dispatch('stopFetching', 'followRequest') store.dispatch('stopFetchingFollowRequests')
store.commit('clearNotifications') store.commit('clearNotifications')
store.commit('resetStatuses') store.commit('resetStatuses')
}) })
@ -469,7 +469,7 @@ const users = {
store.dispatch('initializeSocket') store.dispatch('initializeSocket')
} }
store.dispatch('startMastoSocket').catch((error) => { store.dispatch('startMastoUserSocket').catch((error) => {
console.error('Failed initializing MastoAPI Streaming socket', error) console.error('Failed initializing MastoAPI Streaming socket', error)
// Start getting fresh posts. // Start getting fresh posts.
store.dispatch('startFetchingTimeline', { timeline: 'friends' }) store.dispatch('startFetchingTimeline', { timeline: 'friends' })

View File

@ -24,10 +24,11 @@ const backendInteractorService = credentials => ({
const serv = store.rootState.instance.server.replace('http', 'ws') const serv = store.rootState.instance.server.replace('http', 'ws')
const url = serv + getMastodonSocketURI({ credentials, stream: 'user' }) const url = serv + getMastodonSocketURI({ credentials, stream: 'user' })
const socket = new WebSocket(url) const socket = new WebSocket(url)
console.log(socket) console.debug('Socket created:', socket)
if (socket) { if (socket) {
socket.addEventListener('open', (wsEvent) => console.debug('MastoAPI User WebSocket connection established'))
socket.addEventListener('message', (wsEvent) => onMessage(handleMastoWS(wsEvent))) socket.addEventListener('message', (wsEvent) => onMessage(handleMastoWS(wsEvent)))
socket.addEventListener('error', (error) => console.error('WebSocket Error:', error)) socket.addEventListener('error', (error) => console.error('MastoApi User WebSocket Error:', error))
return socket return socket
} else { } else {
throw new Error('failed to connect to socket') throw new Error('failed to connect to socket')