fix(backend): уменьшить лишние записи SQLite
Docker images / prepare-release (push) Successful in 10s
Docker images / backend-image (push) Successful in 2m8s
Docker images / frontend-image (push) Successful in 3m14s
Docker images / notify-webhook (push) Skipped
Docker images / updater-image (push) Successful in 47s
Docker images / publish-release (push) Successful in 12s
Docker images / prepare-release (push) Successful in 10s
Docker images / backend-image (push) Successful in 2m8s
Docker images / frontend-image (push) Successful in 3m14s
Docker images / notify-webhook (push) Skipped
Docker images / updater-image (push) Successful in 47s
Docker images / publish-release (push) Successful in 12s
Убрать WAL TRUNCATE с hot path NetFlow, не писать неизменённые UPDATE и служебные INSERT, кэшировать карты topology/analytics. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
+68
-1
@@ -8,18 +8,85 @@ import { env } from "../config.js"
|
||||
import * as schema from "./schema.js"
|
||||
|
||||
export const SQLITE_BUSY_TIMEOUT_MS = 5000
|
||||
/** ~16 MiB page cache (negative = KiB). */
|
||||
export const SQLITE_CACHE_SIZE_KIB = 16_000
|
||||
export const SQLITE_WAL_AUTOCHECKPOINT_PAGES = 1000
|
||||
|
||||
export interface SqliteWriteStats {
|
||||
insert: number
|
||||
update: number
|
||||
delete: number
|
||||
walCheckpoint: number
|
||||
}
|
||||
|
||||
let writeTrace: SqliteWriteStats | null = null
|
||||
|
||||
function classifyWriteSql(sql: string): keyof Omit<SqliteWriteStats, "walCheckpoint"> | null {
|
||||
const head = sql.trimStart().slice(0, 12).toUpperCase()
|
||||
if (head.startsWith("INSERT")) return "insert"
|
||||
if (head.startsWith("UPDATE")) return "update"
|
||||
if (head.startsWith("DELETE")) return "delete"
|
||||
return null
|
||||
}
|
||||
|
||||
function installSqliteWriteTrace(handle: SqliteHandle): SqliteHandle {
|
||||
const origPrepare = handle.prepare.bind(handle)
|
||||
handle.prepare = ((sql: string) => {
|
||||
const stmt = origPrepare(sql)
|
||||
const kind = classifyWriteSql(sql)
|
||||
if (!kind) return stmt
|
||||
const origRun = stmt.run.bind(stmt)
|
||||
stmt.run = ((...args: unknown[]) => {
|
||||
if (writeTrace) writeTrace[kind] += 1
|
||||
return origRun(...args)
|
||||
}) as typeof stmt.run
|
||||
return stmt
|
||||
}) as typeof handle.prepare
|
||||
|
||||
const origExec = handle.exec.bind(handle)
|
||||
handle.exec = ((sql: string) => {
|
||||
if (writeTrace) {
|
||||
for (const part of sql.split(";")) {
|
||||
const kind = classifyWriteSql(part)
|
||||
if (kind) writeTrace[kind] += 1
|
||||
}
|
||||
}
|
||||
return origExec(sql)
|
||||
}) as typeof handle.exec
|
||||
|
||||
const origPragma = handle.pragma.bind(handle)
|
||||
handle.pragma = ((source: string, options?: { simple?: boolean }) => {
|
||||
if (writeTrace && /wal_checkpoint/i.test(source)) writeTrace.walCheckpoint += 1
|
||||
return origPragma(source, options as never)
|
||||
}) as typeof handle.pragma
|
||||
|
||||
return handle
|
||||
}
|
||||
|
||||
export function countSqliteWrites<T>(fn: () => T): { result: T; stats: SqliteWriteStats } {
|
||||
const stats: SqliteWriteStats = { insert: 0, update: 0, delete: 0, walCheckpoint: 0 }
|
||||
writeTrace = stats
|
||||
try {
|
||||
return { result: fn(), stats }
|
||||
} finally {
|
||||
writeTrace = null
|
||||
}
|
||||
}
|
||||
|
||||
export function applySqlitePragmas(handle: SqliteHandle): void {
|
||||
handle.pragma("journal_mode = WAL")
|
||||
handle.pragma("foreign_keys = ON")
|
||||
handle.pragma(`busy_timeout = ${SQLITE_BUSY_TIMEOUT_MS}`)
|
||||
handle.pragma("synchronous = NORMAL")
|
||||
handle.pragma(`wal_autocheckpoint = ${SQLITE_WAL_AUTOCHECKPOINT_PAGES}`)
|
||||
handle.pragma("temp_store = MEMORY")
|
||||
handle.pragma(`cache_size = -${SQLITE_CACHE_SIZE_KIB}`)
|
||||
}
|
||||
|
||||
function openSqlite(): SqliteHandle {
|
||||
const handle = new Database(env.DATABASE_PATH)
|
||||
applySqlitePragmas(handle)
|
||||
return handle
|
||||
return installSqliteWriteTrace(handle)
|
||||
}
|
||||
|
||||
let sqlite = openSqlite()
|
||||
|
||||
Reference in New Issue
Block a user