perf: smaller db close implementation

This commit is contained in:
Nolan Lawson 2020-06-27 11:30:47 -07:00
parent 025756324d
commit 9dffb1b622
3 changed files with 47 additions and 59 deletions

View File

@ -7,58 +7,21 @@ import {
STORE_KEYVALUE
} from './constants'
import { uniqEmoji } from './utils/uniqEmoji'
import { jsonChecksum } from './utils/jsonChecksum'
import {
closeDatabase,
deleteDatabase,
addOnCloseListener,
openDatabase,
removeOnCloseListener
openDatabase
} from './databaseLifecycle'
import {
isEmpty, hasData, loadData, getEmojiByGroup,
isEmpty, getEmojiByGroup,
getEmojiBySearchQuery, getEmojiByShortcode, getEmojiByUnicode,
get, set, getTopFavoriteEmoji, incrementFavoriteEmojiCount
} from './idbInterface'
import { log } from '../shared/log'
import { getETag, getETagAndData } from './utils/ajax'
import { customEmojiIndex } from './customEmojiIndex'
import { cleanEmoji } from './utils/cleanEmoji'
async function checkForUpdates (db, dataSource) {
// just do a simple HEAD request first to see if the eTags match
let emojiBaseData
let eTag = await getETag(dataSource)
if (!eTag) { // work around lack of ETag/Access-Control-Expose-Headers
const eTagAndData = await getETagAndData(dataSource)
eTag = eTagAndData[0]
emojiBaseData = eTagAndData[1]
if (!eTag) {
eTag = await jsonChecksum(emojiBaseData)
}
}
if (await hasData(db, dataSource, eTag)) {
log('Database already populated')
} else {
log('Database update available')
if (!emojiBaseData) {
const eTagAndData = await getETagAndData(dataSource)
emojiBaseData = eTagAndData[1]
}
await loadData(db, emojiBaseData, dataSource, eTag)
}
}
async function loadDataForFirstTime (db, dataSource) {
let [eTag, emojiBaseData] = await getETagAndData(dataSource)
if (!eTag) {
// Handle lack of support for ETag or Access-Control-Expose-Headers
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers#Browser_compatibility
eTag = await jsonChecksum(emojiBaseData)
}
await loadData(db, emojiBaseData, dataSource, eTag)
}
import { loadDataForFirstTime, checkForUpdates } from './dataLoading'
export default class Database {
constructor ({ dataSource = DEFAULT_DATA_SOURCE, locale = DEFAULT_LOCALE, customEmoji = [] } = {}) {
@ -177,15 +140,13 @@ export default class Database {
}
}
_clear () { // clear references to IDB, e.g. during a close event
// clear references to IDB, e.g. during a close event
_clear () {
log('_clear database', this._dbName)
// Technically we don't need to call these functions because the memory leak tests
// prove we don't have leaks even with this code commented out. It's because
// We don't need to call removeEventListener or remove the manual "close" listeners.
// The memory leak tests prove this is unnecessary. It's because:
// 1) IDBDatabases that can no longer fire "close" automatically have listeners GCed
// 2) we clear the manual close listeners in databaseLifecycle.js.
// But I am paranoid about memory leaks, so I keep this code here.
this._db.removeEventListener('close', this._clear)
removeOnCloseListener(this._dbName, this._clear)
this._db = this._ready = this._lazyUpdate = undefined
}

View File

@ -0,0 +1,39 @@
import { getETag, getETagAndData } from './utils/ajax'
import { jsonChecksum } from './utils/jsonChecksum'
import { hasData, loadData } from './idbInterface'
import { log } from '../shared/log'
export async function checkForUpdates (db, dataSource) {
// just do a simple HEAD request first to see if the eTags match
let emojiBaseData
let eTag = await getETag(dataSource)
if (!eTag) { // work around lack of ETag/Access-Control-Expose-Headers
const eTagAndData = await getETagAndData(dataSource)
eTag = eTagAndData[0]
emojiBaseData = eTagAndData[1]
if (!eTag) {
eTag = await jsonChecksum(emojiBaseData)
}
}
if (await hasData(db, dataSource, eTag)) {
log('Database already populated')
} else {
log('Database update available')
if (!emojiBaseData) {
const eTagAndData = await getETagAndData(dataSource)
emojiBaseData = eTagAndData[1]
}
await loadData(db, emojiBaseData, dataSource, eTag)
}
}
export async function loadDataForFirstTime (db, dataSource) {
let [eTag, emojiBaseData] = await getETagAndData(dataSource)
if (!eTag) {
// Handle lack of support for ETag or Access-Control-Expose-Headers
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers#Browser_compatibility
eTag = await jsonChecksum(emojiBaseData)
}
await loadData(db, emojiBaseData, dataSource, eTag)
}

View File

@ -70,9 +70,7 @@ export function closeDatabase (dbName) {
const listeners = onCloseListeners[dbName]
if (listeners) {
for (const listener of listeners) {
try {
listener()
} catch (err) { /* ignore */ }
listener()
}
}
}
@ -98,13 +96,3 @@ export function addOnCloseListener (dbName, listener) {
}
listeners.push(listener)
}
export function removeOnCloseListener (dbName, listener) {
const listeners = onCloseListeners[dbName]
if (listeners) {
const idx = listeners.indexOf(listener)
if (idx !== -1) {
listeners.splice(idx, 1)
}
}
}