Pinafore-Web-Client-Frontend/src/routes/_database/cleanup.js

151 lines
4.2 KiB
JavaScript
Raw Normal View History

2018-02-14 04:34:37 +01:00
import { dbPromise, getDatabase } from './databaseLifecycle'
import {
ACCOUNTS_STORE,
NOTIFICATION_TIMELINES_STORE,
NOTIFICATIONS_STORE,
2018-03-09 08:18:18 +01:00
PINNED_STATUSES_STORE,
2018-02-14 04:34:37 +01:00
RELATIONSHIPS_STORE,
STATUS_TIMELINES_STORE,
STATUSES_STORE,
2018-03-09 03:31:59 +01:00
THREADS_STORE,
2018-02-14 04:34:37 +01:00
TIMESTAMP
} from './constants'
import debounce from 'lodash-es/debounce'
2018-02-14 04:34:37 +01:00
import { mark, stop } from '../_utils/marks'
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'
import { scheduleIdleTask } from '../_utils/scheduleIdleTask'
2018-02-14 04:34:37 +01:00
const BATCH_SIZE = 20
2018-02-14 04:35:46 +01:00
function batchedGetAll (callGetAll, callback) {
function nextBatch () {
2018-02-14 04:34:37 +01:00
callGetAll().onsuccess = function (e) {
2019-08-03 22:49:37 +02:00
const results = e.target.result
2018-02-14 04:34:37 +01:00
callback(results)
if (results.length) {
nextBatch()
}
}
}
nextBatch()
}
2018-03-09 03:31:59 +01:00
function cleanupStatuses (statusesStore, statusTimelinesStore, threadsStore, cutoff) {
2018-02-14 04:34:37 +01:00
batchedGetAll(
() => statusesStore.index(TIMESTAMP).getAllKeys(IDBKeyRange.upperBound(cutoff), BATCH_SIZE),
2018-02-14 04:34:37 +01:00
results => {
results.forEach(statusId => {
statusesStore.delete(statusId)
deleteAll(
statusTimelinesStore,
statusTimelinesStore.index('statusId'),
IDBKeyRange.only(statusId)
)
deleteAll(
threadsStore,
threadsStore,
createThreadKeyRange(statusId)
)
2018-02-14 04:34:37 +01:00
})
}
)
}
2018-02-14 04:35:46 +01:00
function cleanupNotifications (notificationsStore, notificationTimelinesStore, cutoff) {
2018-02-14 04:34:37 +01:00
batchedGetAll(
() => notificationsStore.index(TIMESTAMP).getAllKeys(IDBKeyRange.upperBound(cutoff), BATCH_SIZE),
2018-02-14 04:34:37 +01:00
results => {
results.forEach(notificationId => {
notificationsStore.delete(notificationId)
deleteAll(
notificationTimelinesStore,
notificationTimelinesStore.index('notificationId'),
IDBKeyRange.only(notificationId)
)
2018-02-14 04:34:37 +01:00
})
}
)
}
2018-03-09 08:18:18 +01:00
function cleanupAccounts (accountsStore, pinnedStatusesStore, cutoff) {
2018-02-14 04:34:37 +01:00
batchedGetAll(
() => accountsStore.index(TIMESTAMP).getAllKeys(IDBKeyRange.upperBound(cutoff), BATCH_SIZE),
results => {
results.forEach(accountId => {
accountsStore.delete(accountId)
deleteAll(
pinnedStatusesStore,
pinnedStatusesStore,
createPinnedStatusKeyRange(accountId)
)
2018-02-14 04:34:37 +01:00
})
}
)
}
2018-02-14 04:35:46 +01:00
function cleanupRelationships (relationshipsStore, cutoff) {
2018-02-14 04:34:37 +01:00
batchedGetAll(
() => relationshipsStore.index(TIMESTAMP).getAllKeys(IDBKeyRange.upperBound(cutoff), BATCH_SIZE),
results => {
results.forEach(relationshipId => {
relationshipsStore.delete(relationshipId)
2018-02-14 04:34:37 +01:00
})
}
)
}
export async function cleanup (instanceName) {
2018-02-14 04:34:37 +01:00
console.log('cleanup', instanceName)
mark(`cleanup:${instanceName}`)
2019-08-03 22:49:37 +02:00
const db = await getDatabase(instanceName)
const storeNames = [
2018-02-14 04:34:37 +01:00
STATUSES_STORE,
STATUS_TIMELINES_STORE,
NOTIFICATIONS_STORE,
NOTIFICATION_TIMELINES_STORE,
ACCOUNTS_STORE,
2018-03-09 03:31:59 +01:00
RELATIONSHIPS_STORE,
2018-03-09 08:18:18 +01:00
THREADS_STORE,
PINNED_STATUSES_STORE
2018-02-14 04:34:37 +01:00
]
await dbPromise(db, storeNames, 'readwrite', (stores) => {
2019-08-03 22:49:37 +02:00
const [
2018-02-14 04:34:37 +01:00
statusesStore,
statusTimelinesStore,
notificationsStore,
notificationTimelinesStore,
accountsStore,
2018-03-09 03:31:59 +01:00
relationshipsStore,
2018-03-09 08:18:18 +01:00
threadsStore,
pinnedStatusesStore
2018-02-14 04:34:37 +01:00
] = stores
const cutoff = Date.now() - CLEANUP_TIME_AGO
2018-02-14 04:34:37 +01:00
2018-03-09 03:31:59 +01:00
cleanupStatuses(statusesStore, statusTimelinesStore, threadsStore, cutoff)
2018-02-14 04:34:37 +01:00
cleanupNotifications(notificationsStore, notificationTimelinesStore, cutoff)
2018-03-09 08:18:18 +01:00
cleanupAccounts(accountsStore, pinnedStatusesStore, cutoff)
2018-02-14 04:34:37 +01:00
cleanupRelationships(relationshipsStore, cutoff)
})
stop(`cleanup:${instanceName}`)
}
2018-02-14 04:35:46 +01:00
function doCleanup (instanceName) {
scheduleIdleTask(() => cleanup(instanceName))
2018-02-14 04:34:37 +01:00
}
async function scheduledCleanup () {
2018-02-14 04:34:37 +01:00
console.log('scheduledCleanup')
2019-08-03 22:49:37 +02:00
const knownInstances = await getKnownInstances()
for (const instance of knownInstances) {
2018-02-14 04:34:37 +01:00
doCleanup(instance)
}
}
// we have unit tests that test indexedDB; we don't want this thing to run forever
export const scheduleCleanup = process.browser ? debounce(scheduledCleanup, CLEANUP_DELAY) : noop