From 584d94eea465cce2e259ba085a84e44104848cc9 Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Mon, 2 Apr 2018 21:14:12 -0700 Subject: [PATCH] fix streaming gap issue for instance switching --- routes/_actions/addStatusOrNotification.js | 2 +- routes/_store/observers/instanceObservers.js | 51 ++++++++++++++++++-- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/routes/_actions/addStatusOrNotification.js b/routes/_actions/addStatusOrNotification.js index 70eec628..c5df4557 100644 --- a/routes/_actions/addStatusOrNotification.js +++ b/routes/_actions/addStatusOrNotification.js @@ -32,7 +32,7 @@ async function insertUpdatesIntoTimeline (instanceName, timelineName, updates) { let itemIdsToAdd = store.getForTimeline(instanceName, timelineName, 'itemIdsToAdd') || [] itemIdsToAdd = uniq(itemIdsToAdd.concat(updates.map(_ => _.id))) - console.log('adding ', itemIdsToAdd.length, 'items to itemIdsToAdd') + console.log('adding ', itemIdsToAdd.length, 'items to itemIdsToAdd on instance', instanceName, 'on timeline', timelineName) store.setForTimeline(instanceName, timelineName, {itemIdsToAdd: itemIdsToAdd}) } diff --git a/routes/_store/observers/instanceObservers.js b/routes/_store/observers/instanceObservers.js index ac78e577..1630fd11 100644 --- a/routes/_store/observers/instanceObservers.js +++ b/routes/_store/observers/instanceObservers.js @@ -2,6 +2,8 @@ import { updateInstanceInfo, updateVerifyCredentialsForInstance } from '../../_a import { updateLists } from '../../_actions/lists' import { createStream } from '../../_actions/streaming' import { updateCustomEmojiForInstance } from '../../_actions/emoji' +import { addStatusesOrNotifications } from '../../_actions/addStatusOrNotification' +import { getTimeline } from '../../_api/timelines' export function instanceObservers (store) { // stream to watch for home timeline updates and notifications @@ -27,14 +29,55 @@ export function instanceObservers (store) { updateLists() await updateInstanceInfo(currentInstance) - let instanceInfo = store.get('currentInstanceInfo') - if (!(instanceInfo && store.get('currentInstance') === currentInstance)) { + + let currentInstanceIsUnchanged = () => { + return store.get('currentInstance') === currentInstance + } + + if (!currentInstanceIsUnchanged()) { return } + let instanceInfo = store.get('currentInstanceInfo') + if (!instanceInfo) { + 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) + if (newTimelineItems.length) { + addStatusesOrNotifications(currentInstance, timelineName, newTimelineItems) + } + } + + await Promise.all([ + fillGap('home', firstHomeTimelineItemId), + fillGap('notifications', firstNotificationTimelineItemId) + ]) + } + let accessToken = store.get('accessToken') - currentInstanceStream = createStream(instanceInfo.urls.streaming_api, - currentInstance, accessToken, 'home') + let streamingApi = instanceInfo.urls.streaming_api + currentInstanceStream = createStream(streamingApi, + currentInstance, accessToken, 'home', onOpenStream) if (process.env.NODE_ENV !== 'production') { window.currentInstanceStream = currentInstanceStream