fix(sqlite): cleanup on exit
This commit is contained in:
parent
02a6a0e133
commit
62e8e3b33f
1 changed files with 40 additions and 21 deletions
|
@ -4,6 +4,7 @@ import sqlite3, { Options } from 'better-sqlite3'
|
||||||
|
|
||||||
import { ITelegramStorage, mtp, tl, toggleChannelIdMark } from '@mtcute/core'
|
import { ITelegramStorage, mtp, tl, toggleChannelIdMark } from '@mtcute/core'
|
||||||
import {
|
import {
|
||||||
|
beforeExit,
|
||||||
Logger,
|
Logger,
|
||||||
longFromFastString,
|
longFromFastString,
|
||||||
longToFastString,
|
longToFastString,
|
||||||
|
@ -211,6 +212,7 @@ export class SqliteStorage implements ITelegramStorage /*, IStateStorage*/ {
|
||||||
|
|
||||||
private _vacuumTimeout?: NodeJS.Timeout
|
private _vacuumTimeout?: NodeJS.Timeout
|
||||||
private _vacuumInterval: number
|
private _vacuumInterval: number
|
||||||
|
private _cleanupUnregister?: () => void
|
||||||
|
|
||||||
private log!: Logger
|
private log!: Logger
|
||||||
private readerMap!: TlReaderMap
|
private readerMap!: TlReaderMap
|
||||||
|
@ -296,6 +298,13 @@ export class SqliteStorage implements ITelegramStorage /*, IStateStorage*/ {
|
||||||
* @default `300_000` (5 minutes)
|
* @default `300_000` (5 minutes)
|
||||||
*/
|
*/
|
||||||
vacuumInterval?: number
|
vacuumInterval?: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to finalize database before exiting.
|
||||||
|
*
|
||||||
|
* @default `true`
|
||||||
|
*/
|
||||||
|
cleanup?: boolean
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
this._filename = filename
|
this._filename = filename
|
||||||
|
@ -314,28 +323,14 @@ export class SqliteStorage implements ITelegramStorage /*, IStateStorage*/ {
|
||||||
|
|
||||||
this._wal = !params?.disableWal
|
this._wal = !params?.disableWal
|
||||||
|
|
||||||
this._saveUnimportantLater = throttle(
|
this._saveUnimportant = this._saveUnimportant.bind(this)
|
||||||
() => {
|
this._saveUnimportantLater = throttle(this._saveUnimportant, params?.unimportantSavesDelay ?? 30000)
|
||||||
// unimportant changes are changes about cached in memory entities,
|
|
||||||
// that don't really need to be cached right away.
|
|
||||||
// to avoid redundant DB calls, these changes are persisted
|
|
||||||
// no more than once every 30 seconds.
|
|
||||||
//
|
|
||||||
// additionally, to avoid redundant changes that
|
|
||||||
// are immediately overwritten, we use object instead
|
|
||||||
// of an array, where the key is marked peer id,
|
|
||||||
// and value is the arguments array, since
|
|
||||||
// the query is always `updateCachedEnt`
|
|
||||||
const items = Object.values(this._pendingUnimportant)
|
|
||||||
if (!items.length) return
|
|
||||||
|
|
||||||
this._updateManyPeers(items)
|
|
||||||
this._pendingUnimportant = {}
|
|
||||||
},
|
|
||||||
params?.unimportantSavesDelay ?? 30000,
|
|
||||||
)
|
|
||||||
|
|
||||||
this._vacuumInterval = params?.vacuumInterval ?? 300_000
|
this._vacuumInterval = params?.vacuumInterval ?? 300_000
|
||||||
|
|
||||||
|
if (params?.cleanup !== false) {
|
||||||
|
this._cleanupUnregister = beforeExit(() => this._destroy())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setup(log: Logger, readerMap: TlReaderMap, writerMap: TlWriterMap): void {
|
setup(log: Logger, readerMap: TlReaderMap, writerMap: TlWriterMap): void {
|
||||||
|
@ -493,6 +488,24 @@ export class SqliteStorage implements ITelegramStorage /*, IStateStorage*/ {
|
||||||
this._vacuumTimeout = setInterval(this._vacuum.bind(this), this._vacuumInterval)
|
this._vacuumTimeout = setInterval(this._vacuum.bind(this), this._vacuumInterval)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _saveUnimportant() {
|
||||||
|
// unimportant changes are changes about cached in memory entities,
|
||||||
|
// that don't really need to be cached right away.
|
||||||
|
// to avoid redundant DB calls, these changes are persisted
|
||||||
|
// no more than once every 30 seconds.
|
||||||
|
//
|
||||||
|
// additionally, to avoid redundant changes that
|
||||||
|
// are immediately overwritten, we use object instead
|
||||||
|
// of an array, where the key is marked peer id,
|
||||||
|
// and value is the arguments array, since
|
||||||
|
// the query is always `updateCachedEnt`
|
||||||
|
const items = Object.values(this._pendingUnimportant)
|
||||||
|
if (!items.length) return
|
||||||
|
|
||||||
|
this._updateManyPeers(items)
|
||||||
|
this._pendingUnimportant = {}
|
||||||
|
}
|
||||||
|
|
||||||
save(): void {
|
save(): void {
|
||||||
if (!this._pending.length) return
|
if (!this._pending.length) return
|
||||||
|
|
||||||
|
@ -502,12 +515,18 @@ export class SqliteStorage implements ITelegramStorage /*, IStateStorage*/ {
|
||||||
this._saveUnimportantLater()
|
this._saveUnimportantLater()
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy(): void {
|
private _destroy() {
|
||||||
|
this._saveUnimportant()
|
||||||
this._db.close()
|
this._db.close()
|
||||||
clearInterval(this._vacuumTimeout)
|
clearInterval(this._vacuumTimeout)
|
||||||
this._saveUnimportantLater.reset()
|
this._saveUnimportantLater.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
destroy(): void {
|
||||||
|
this._destroy()
|
||||||
|
this._cleanupUnregister?.()
|
||||||
|
}
|
||||||
|
|
||||||
reset(withAuthKeys = false): void {
|
reset(withAuthKeys = false): void {
|
||||||
this._db.exec(RESET)
|
this._db.exec(RESET)
|
||||||
if (withAuthKeys) this._db.exec(RESET_AUTH_KEYS)
|
if (withAuthKeys) this._db.exec(RESET_AUTH_KEYS)
|
||||||
|
|
Loading…
Reference in a new issue