Dokumentasi ini menjelaskan proses migrasi dari database Level ke LMDB dalam proyek browser-private-api-proxy-server.
File baru src/db/LmdbDb.ts telah dibuat untuk mengimplementasikan fungsi-fungsi yang sama dengan LevelDb.ts tetapi menggunakan LMDB sebagai database backend.
Perbedaan utama antara implementasi Level dan LMDB:
- Library: Menggunakan
opendarilmdbalih-alihLeveldarilevel - Inisialisasi Database: LMDB menggunakan
open()dengan objek konfigurasi - Operasi Delete: LMDB menggunakan
remove()alih-alihdel() - Operasi Batch: LMDB menggunakan transaksi manual untuk operasi batch
- Operasi Find/Range: Implementasi yang berbeda untuk iterasi data dengan prefix
File src/db/store.ts telah diperbarui untuk menggunakan LmdbDb alih-alih LevelDb:
import { dbConfig } from "./config"
import { LmdbDb } from "./LmdbDb" // Diubah dari LevelDb
import path from "path"
const kvstore = new LmdbDb(path.join(process.cwd(), dbConfig.path, dbConfig.folder))
export { kvstore }Kelas LmdbDb dirancang untuk memiliki API yang kompatibel dengan LevelDb:
put(key, value): Menyimpan data dengan key tertentuget(key): Mengambil data berdasarkan keydelete(key): Menghapus data berdasarkan keyfind({ prefix }): Mencari data dengan prefix tertentubatch(operations): Melakukan operasi batch (put/delete)getDb(): Mengambil instance databaseclose(): Menutup koneksi database
Level:
this.db = new Level(dbPath, { valueEncoding: "json" })LMDB:
this.db = open({
path: dbPath,
compression: true,
})Level:
await this.db.del(key)LMDB:
await this.db.remove(key)Level:
const iterator = this.db.iterator({
gt: prefix,
lt: prefix + "z".repeat(10),
})
for await (const [key, val] of iterator) {
if (key.startsWith(prefix)) {
results.push({ key, value: val })
}
}LMDB:
const range = this.db.getRange({
start: prefix,
end: prefix + "\uffff",
})
for (const entry of range) {
const { key, value } = entry
if (key.startsWith(prefix)) {
results.push({ key, value })
}
}Level:
await this.db.batch(batchList)LMDB:
const txn = this.db.transaction()
try {
for (const operation of batchList) {
if (operation.type === "put") {
txn.put(operation.key, operation.value)
} else if (operation.type === "del") {
txn.remove(operation.key)
}
}
await txn.commit()
} catch (error) {
await txn.abort()
throw error
}Implementasi LMDB telah diuji dengan file src/db/level-db-example.ts dan berhasil:
- Menyisipkan data administrator
- Mencari data dengan prefix "administrator_"
- Menemukan data spesifik berdasarkan key
- Performa: LMDB umumnya lebih cepat untuk operasi baca/tulis
- Konkurensi: Mendukung akses konkuren tanpa locking
- Ukuran File: Database LMDB cenderung lebih kompak
- Memory-Mapped: Menggunakan memory-mapped files untuk efisiensi
- Data yang ada di database Level tidak akan otomatis tersedia di LMDB
- Jika ada data penting di Level, perlu dilakukan migrasi data secara manual
- Konfigurasi LMDB dapat disesuaikan lebih lanjut sesuai kebutuhan aplikasi