perf: periodically clean up old compose drafts (#1469)

fixes #1419
This commit is contained in:
Nolan Lawson 2019-09-07 17:49:58 -07:00 committed by GitHub
parent 9c79b69497
commit df0afa12ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 46 additions and 7 deletions

View file

@ -16,10 +16,9 @@ import { deleteAll } from './utils'
import { createPinnedStatusKeyRange, createThreadKeyRange } from './keys'
import { getKnownInstances } from './knownInstances'
import noop from 'lodash-es/noop'
import { CLEANUP_DELAY, CLEANUP_TIME_AGO } from '../_static/database'
const BATCH_SIZE = 20
export const TIME_AGO = 5 * 24 * 60 * 60 * 1000 // five days ago
const DELAY = 5 * 60 * 1000 // five minutes
function batchedGetAll (callGetAll, callback) {
function nextBatch () {
@ -124,7 +123,7 @@ export async function cleanup (instanceName) {
pinnedStatusesStore
] = stores
const cutoff = Date.now() - TIME_AGO
const cutoff = Date.now() - CLEANUP_TIME_AGO
cleanupStatuses(statusesStore, statusTimelinesStore, threadsStore, cutoff)
cleanupNotifications(notificationsStore, notificationTimelinesStore, cutoff)
@ -148,4 +147,4 @@ async function scheduledCleanup () {
}
// we have unit tests that test indexedDB; we don't want this thing to run forever
export const scheduleCleanup = process.browser ? debounce(scheduledCleanup, DELAY) : noop
export const scheduleCleanup = process.browser ? debounce(scheduledCleanup, CLEANUP_DELAY) : noop

View file

@ -0,0 +1,2 @@
export const CLEANUP_TIME_AGO = 5 * 24 * 60 * 60 * 1000 // five days ago
export const CLEANUP_DELAY = 5 * 60 * 1000 // five minutes

View file

@ -4,7 +4,11 @@ export function instanceMixins (Store) {
Store.prototype.setComposeData = function (realm, obj) {
const { composeData, currentInstance } = this.get()
const instanceNameData = composeData[currentInstance] = composeData[currentInstance] || {}
instanceNameData[realm] = Object.assign(instanceNameData[realm] || {}, obj)
instanceNameData[realm] = Object.assign(
instanceNameData[realm] || {},
{ ts: Date.now() },
obj
)
this.set({ composeData })
}

View file

@ -0,0 +1,31 @@
import { store } from '../store'
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
import { CLEANUP_DELAY, CLEANUP_TIME_AGO } from '../../_static/database'
function doCleanup () {
// Periodically clean up drafts in localStorage, so they don't grow without bound.
// Only do this for replies, so not for the home timeline or the compose modal.
const now = Date.now()
let changeCount = 0
const { composeData } = store.get()
for (const instanceComposeData of Object.values(composeData)) {
for (const [realm, timelineComposeData] of Object.entries(instanceComposeData)) {
if (realm === 'home' || realm === 'dialog') {
continue
}
const ts = timelineComposeData.ts || 0 // if no timestamp set, just assume it's very old (migration behavior)
if (now - ts > CLEANUP_TIME_AGO) {
delete instanceComposeData[realm]
changeCount++
}
}
}
console.log('deleted', changeCount, 'old drafts')
if (changeCount) {
store.set({ composeData })
}
}
export function cleanup () {
setInterval(() => scheduleIdleTask(doCleanup), CLEANUP_DELAY)
}

View file

@ -4,6 +4,7 @@ import { notificationObservers } from './notificationObservers'
import { autosuggestObservers } from './autosuggestObservers'
import { notificationPermissionObservers } from './notificationPermissionObservers'
import { customScrollbarObservers } from './customScrollbarObservers'
import { cleanup } from './cleanup'
// These observers can be lazy-loaded when the user is actually logged in.
// Prevents circular dependencies and reduces the size of main.js
@ -14,4 +15,5 @@ export default function loggedInObservers () {
autosuggestObservers()
notificationPermissionObservers()
customScrollbarObservers()
cleanup()
}

View file

@ -10,7 +10,8 @@ import {
TIMESTAMP, ACCOUNT_ID, STATUS_ID, REBLOG_ID, USERNAME_LOWERCASE,
CURRENT_TIME, DB_VERSION_CURRENT, DB_VERSION_SEARCH_ACCOUNTS, DB_VERSION_SNOWFLAKE_IDS
} from '../../src/routes/_database/constants'
import { cleanup, TIME_AGO } from '../../src/routes/_database/cleanup'
import { cleanup } from '../../src/routes/_database/cleanup'
import { CLEANUP_TIME_AGO } from '../../src/routes/_static/database'
const INSTANCE_NAME = 'localhost:3000'
@ -91,7 +92,7 @@ describe('test-database.js', function () {
// set a timestamp based on the *current* date when the status is inserted,
// not the date that the status was composed.
const longAgo = Date.now() - (TIME_AGO * 2)
const longAgo = Date.now() - (CLEANUP_TIME_AGO * 2)
const oldStatus = {
id: '1',