forked from cybrespace/pinafore
fix(observers): refactor instance observers, minor optimizations (#730)
try to defer more work, split everything up into more functional code for easier reading
This commit is contained in:
parent
ef32bfb278
commit
f7164dd4c0
|
@ -3,16 +3,17 @@ import { getLists } from '../_api/lists'
|
|||
import { cacheFirstUpdateAfter } from '../_utils/sync'
|
||||
import { database } from '../_database/database'
|
||||
|
||||
export async function updateLists () {
|
||||
let { currentInstance, accessToken } = store.get()
|
||||
export async function updateListsForInstance (instanceName) {
|
||||
let { loggedInInstances } = store.get()
|
||||
let accessToken = loggedInInstances[instanceName].access_token
|
||||
|
||||
await cacheFirstUpdateAfter(
|
||||
() => getLists(currentInstance, accessToken),
|
||||
() => database.getLists(currentInstance),
|
||||
lists => database.setLists(currentInstance, lists),
|
||||
() => getLists(instanceName, accessToken),
|
||||
() => database.getLists(instanceName),
|
||||
lists => database.setLists(instanceName, lists),
|
||||
lists => {
|
||||
let { instanceLists } = store.get()
|
||||
instanceLists[currentInstance] = lists
|
||||
instanceLists[instanceName] = lists
|
||||
store.set({ instanceLists: instanceLists })
|
||||
}
|
||||
)
|
||||
|
|
|
@ -92,13 +92,13 @@
|
|||
import HiddenFromSSR from '../../_components/HiddenFromSSR'
|
||||
import PageList from '../../_components/community/PageList.html'
|
||||
import PageListItem from '../../_components/community/PageListItem.html'
|
||||
import { updateLists } from '../../_actions/lists'
|
||||
import { updateListsForInstance } from '../../_actions/lists'
|
||||
|
||||
export default {
|
||||
async oncreate () {
|
||||
let { currentInstance } = this.store.get()
|
||||
if (currentInstance) {
|
||||
await updateLists()
|
||||
await updateListsForInstance(currentInstance)
|
||||
}
|
||||
},
|
||||
store: () => store,
|
||||
|
@ -112,4 +112,4 @@
|
|||
isLockedAccount: ({ $currentVerifyCredentials }) => $currentVerifyCredentials && $currentVerifyCredentials.locked
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -1,16 +1,98 @@
|
|||
import { updateInstanceInfo, updateVerifyCredentialsForInstance } from '../../_actions/instances'
|
||||
import { updateLists } from '../../_actions/lists'
|
||||
import { updateListsForInstance } from '../../_actions/lists'
|
||||
import { createStream } from '../../_actions/streaming'
|
||||
import { updatePushSubscriptionForInstance } from '../../_actions/pushSubscription'
|
||||
import { updateCustomEmojiForInstance } from '../../_actions/emoji'
|
||||
import { addStatusesOrNotifications } from '../../_actions/addStatusOrNotification'
|
||||
import { getTimeline } from '../../_api/timelines'
|
||||
import { TIMELINE_BATCH_SIZE } from '../../_static/timelines'
|
||||
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
|
||||
import { mark, stop } from '../../_utils/marks'
|
||||
|
||||
// stream to watch for home timeline updates and notifications
|
||||
let currentInstanceStream
|
||||
|
||||
async function refreshInstanceDataAndStream (store, instanceName) {
|
||||
mark(`refreshInstanceDataAndStream-${instanceName}`)
|
||||
await doRefreshInstanceDataAndStream(store, instanceName)
|
||||
stop(`refreshInstanceDataAndStream-${instanceName}`)
|
||||
}
|
||||
|
||||
function currentInstanceChanged (store, instanceName) {
|
||||
return store.get().currentInstance !== instanceName
|
||||
}
|
||||
|
||||
async function doRefreshInstanceDataAndStream (store, instanceName) {
|
||||
if (currentInstanceChanged(store, instanceName)) {
|
||||
return
|
||||
}
|
||||
|
||||
await refreshInstanceData(instanceName)
|
||||
|
||||
if (currentInstanceChanged(store, instanceName)) {
|
||||
return
|
||||
}
|
||||
|
||||
let { currentInstanceInfo } = store.get()
|
||||
if (!currentInstanceInfo) {
|
||||
return
|
||||
}
|
||||
|
||||
stream(store, instanceName, currentInstanceInfo)
|
||||
}
|
||||
|
||||
async function refreshInstanceData (instanceName) {
|
||||
// these are all low-priority
|
||||
scheduleIdleTask(() => updateVerifyCredentialsForInstance(instanceName))
|
||||
scheduleIdleTask(() => updateCustomEmojiForInstance(instanceName))
|
||||
scheduleIdleTask(() => updateListsForInstance(instanceName))
|
||||
scheduleIdleTask(() => updatePushSubscriptionForInstance(instanceName))
|
||||
|
||||
// this is the only critical one
|
||||
await updateInstanceInfo(instanceName)
|
||||
}
|
||||
|
||||
function stream (store, instanceName, currentInstanceInfo) {
|
||||
let homeTimelineItemIds = store.getForTimeline(instanceName,
|
||||
'home', 'timelineItemIds')
|
||||
let firstHomeTimelineItemId = homeTimelineItemIds && homeTimelineItemIds[0]
|
||||
let notificationItemIds = store.getForTimeline(instanceName,
|
||||
'notifications', 'timelineItemIds')
|
||||
let firstNotificationTimelineItemId = notificationItemIds && notificationItemIds[0]
|
||||
|
||||
let { accessToken } = store.get()
|
||||
let streamingApi = currentInstanceInfo.urls.streaming_api
|
||||
|
||||
function onOpenStream () {
|
||||
if (currentInstanceChanged(store, instanceName)) {
|
||||
return
|
||||
}
|
||||
|
||||
/* no await */ fillGap(instanceName, accessToken, 'home', firstHomeTimelineItemId)
|
||||
/* no await */ fillGap(instanceName, accessToken, 'notifications', firstNotificationTimelineItemId)
|
||||
}
|
||||
|
||||
currentInstanceStream = createStream(streamingApi, instanceName, accessToken, 'home', onOpenStream)
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
window.currentInstanceStream = currentInstanceStream
|
||||
}
|
||||
}
|
||||
|
||||
// fill in the "streaming gap" – i.e. fetch the most recent 20 items so that there isn't
|
||||
// a big gap in the timeline if you haven't looked at it in awhile
|
||||
async function fillGap (instanceName, accessToken, timelineName, firstTimelineItemId) {
|
||||
if (!firstTimelineItemId) {
|
||||
return
|
||||
}
|
||||
let newTimelineItems = await getTimeline(instanceName, accessToken,
|
||||
timelineName, null, firstTimelineItemId, TIMELINE_BATCH_SIZE)
|
||||
if (newTimelineItems.length) {
|
||||
addStatusesOrNotifications(instanceName, timelineName, newTimelineItems)
|
||||
}
|
||||
}
|
||||
|
||||
export function instanceObservers (store) {
|
||||
// stream to watch for home timeline updates and notifications
|
||||
let currentInstanceStream
|
||||
|
||||
store.observe('currentInstance', async (currentInstance) => {
|
||||
if (!process.browser) {
|
||||
return
|
||||
|
@ -26,64 +108,6 @@ export function instanceObservers (store) {
|
|||
return
|
||||
}
|
||||
|
||||
/* no await */ updateVerifyCredentialsForInstance(currentInstance)
|
||||
/* no await */ updateCustomEmojiForInstance(currentInstance)
|
||||
/* no await */ updateLists()
|
||||
/* no await */ updatePushSubscriptionForInstance(currentInstance)
|
||||
await updateInstanceInfo(currentInstance)
|
||||
|
||||
let currentInstanceIsUnchanged = () => {
|
||||
let { currentInstance: newCurrentInstance } = store.get()
|
||||
return newCurrentInstance === currentInstance
|
||||
}
|
||||
|
||||
if (!currentInstanceIsUnchanged()) {
|
||||
return
|
||||
}
|
||||
|
||||
let { currentInstanceInfo } = store.get()
|
||||
if (!currentInstanceInfo) {
|
||||
return
|
||||
}
|
||||
|
||||
let homeTimelineItemIds = store.getForTimeline(currentInstance,
|
||||
'home', 'timelineItemIds')
|
||||
let firstHomeTimelineItemId = homeTimelineItemIds && homeTimelineItemIds[0]
|
||||
let notificationItemIds = store.getForTimeline(currentInstance,
|
||||
'notifications', 'timelineItemIds')
|
||||
let firstNotificationTimelineItemId = notificationItemIds && notificationItemIds[0]
|
||||
|
||||
let onOpenStream = async () => {
|
||||
if (!currentInstanceIsUnchanged()) {
|
||||
return
|
||||
}
|
||||
|
||||
// fill in the "streaming gap" – i.e. fetch the most recent 20 items so that there isn't
|
||||
// a big gap in the timeline if you haven't looked at it in awhile
|
||||
async function fillGap (timelineName, firstTimelineItemId) {
|
||||
if (!firstTimelineItemId) {
|
||||
return
|
||||
}
|
||||
let newTimelineItems = await getTimeline(currentInstance, accessToken,
|
||||
timelineName, null, firstTimelineItemId, TIMELINE_BATCH_SIZE)
|
||||
if (newTimelineItems.length) {
|
||||
addStatusesOrNotifications(currentInstance, timelineName, newTimelineItems)
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
fillGap('home', firstHomeTimelineItemId),
|
||||
fillGap('notifications', firstNotificationTimelineItemId)
|
||||
])
|
||||
}
|
||||
|
||||
let { accessToken } = store.get()
|
||||
let streamingApi = currentInstanceInfo.urls.streaming_api
|
||||
currentInstanceStream = createStream(streamingApi,
|
||||
currentInstance, accessToken, 'home', onOpenStream)
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
window.currentInstanceStream = currentInstanceStream
|
||||
}
|
||||
scheduleIdleTask(() => refreshInstanceDataAndStream(store, currentInstance))
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue