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 { cacheFirstUpdateAfter } from '../_utils/sync'
|
||||||
import { database } from '../_database/database'
|
import { database } from '../_database/database'
|
||||||
|
|
||||||
export async function updateLists () {
|
export async function updateListsForInstance (instanceName) {
|
||||||
let { currentInstance, accessToken } = store.get()
|
let { loggedInInstances } = store.get()
|
||||||
|
let accessToken = loggedInInstances[instanceName].access_token
|
||||||
|
|
||||||
await cacheFirstUpdateAfter(
|
await cacheFirstUpdateAfter(
|
||||||
() => getLists(currentInstance, accessToken),
|
() => getLists(instanceName, accessToken),
|
||||||
() => database.getLists(currentInstance),
|
() => database.getLists(instanceName),
|
||||||
lists => database.setLists(currentInstance, lists),
|
lists => database.setLists(instanceName, lists),
|
||||||
lists => {
|
lists => {
|
||||||
let { instanceLists } = store.get()
|
let { instanceLists } = store.get()
|
||||||
instanceLists[currentInstance] = lists
|
instanceLists[instanceName] = lists
|
||||||
store.set({ instanceLists: instanceLists })
|
store.set({ instanceLists: instanceLists })
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -92,13 +92,13 @@
|
||||||
import HiddenFromSSR from '../../_components/HiddenFromSSR'
|
import HiddenFromSSR from '../../_components/HiddenFromSSR'
|
||||||
import PageList from '../../_components/community/PageList.html'
|
import PageList from '../../_components/community/PageList.html'
|
||||||
import PageListItem from '../../_components/community/PageListItem.html'
|
import PageListItem from '../../_components/community/PageListItem.html'
|
||||||
import { updateLists } from '../../_actions/lists'
|
import { updateListsForInstance } from '../../_actions/lists'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
async oncreate () {
|
async oncreate () {
|
||||||
let { currentInstance } = this.store.get()
|
let { currentInstance } = this.store.get()
|
||||||
if (currentInstance) {
|
if (currentInstance) {
|
||||||
await updateLists()
|
await updateListsForInstance(currentInstance)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
store: () => store,
|
store: () => store,
|
||||||
|
|
|
@ -1,16 +1,98 @@
|
||||||
import { updateInstanceInfo, updateVerifyCredentialsForInstance } from '../../_actions/instances'
|
import { updateInstanceInfo, updateVerifyCredentialsForInstance } from '../../_actions/instances'
|
||||||
import { updateLists } from '../../_actions/lists'
|
import { updateListsForInstance } from '../../_actions/lists'
|
||||||
import { createStream } from '../../_actions/streaming'
|
import { createStream } from '../../_actions/streaming'
|
||||||
import { updatePushSubscriptionForInstance } from '../../_actions/pushSubscription'
|
import { updatePushSubscriptionForInstance } from '../../_actions/pushSubscription'
|
||||||
import { updateCustomEmojiForInstance } from '../../_actions/emoji'
|
import { updateCustomEmojiForInstance } from '../../_actions/emoji'
|
||||||
import { addStatusesOrNotifications } from '../../_actions/addStatusOrNotification'
|
import { addStatusesOrNotifications } from '../../_actions/addStatusOrNotification'
|
||||||
import { getTimeline } from '../../_api/timelines'
|
import { getTimeline } from '../../_api/timelines'
|
||||||
import { TIMELINE_BATCH_SIZE } from '../../_static/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) {
|
export function instanceObservers (store) {
|
||||||
// stream to watch for home timeline updates and notifications
|
|
||||||
let currentInstanceStream
|
|
||||||
|
|
||||||
store.observe('currentInstance', async (currentInstance) => {
|
store.observe('currentInstance', async (currentInstance) => {
|
||||||
if (!process.browser) {
|
if (!process.browser) {
|
||||||
return
|
return
|
||||||
|
@ -26,64 +108,6 @@ export function instanceObservers (store) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/* no await */ updateVerifyCredentialsForInstance(currentInstance)
|
scheduleIdleTask(() => refreshInstanceDataAndStream(store, 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
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue