From 3378fe3176dccceb9bf11fce9ca416ef533c4fcb Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Wed, 29 Dec 2021 16:26:12 +0900
Subject: [PATCH] Use lokijs instead of nedb for marker database
---
package.json | 2 ++
src/main/database.ts | 22 +++++++++++++++
src/main/index.ts | 24 ++++++++++++----
src/main/marker.ts | 66 +++++++++++++++++++++++++-------------------
yarn.lock | 10 +++++++
5 files changed, 90 insertions(+), 34 deletions(-)
create mode 100644 src/main/database.ts
diff --git a/package.json b/package.json
index b22c5a37..93bb7ffd 100644
--- a/package.json
+++ b/package.json
@@ -87,6 +87,7 @@
"emoji-mart-vue": "^2.6.6",
"i18next": "^21.3.3",
"lodash": "^4.17.21",
+ "lokijs": "^1.5.12",
"megalodon": "3.6.7",
"minimist": "^1.2.5",
"moment": "^2.29.1",
@@ -125,6 +126,7 @@
"@types/i18next": "^13.0.0",
"@types/jest": "27.0.2",
"@types/lodash": "^4.14.176",
+ "@types/lokijs": "^1.5.7",
"@types/nedb": "^1.8.12",
"@types/node": "^16.11.6",
"@types/parse-link-header": "^1.0.0",
diff --git a/src/main/database.ts b/src/main/database.ts
new file mode 100644
index 00000000..51558345
--- /dev/null
+++ b/src/main/database.ts
@@ -0,0 +1,22 @@
+import Loki from 'lokijs'
+
+const newDB = (file: string): Promise => {
+ return new Promise(resolve => {
+ const databaseInitializer = () => {
+ let markers = db.getCollection('markers')
+ if (markers === null) {
+ markers = db.addCollection('markers')
+ }
+ resolve(db)
+ }
+
+ const db = new Loki(file, {
+ autoload: true,
+ autosave: true,
+ autosaveInterval: 4000,
+ autoloadCallback: databaseInitializer
+ })
+ })
+}
+
+export default newDB
diff --git a/src/main/index.ts b/src/main/index.ts
index 5134de43..5a30aa18 100644
--- a/src/main/index.ts
+++ b/src/main/index.ts
@@ -55,6 +55,7 @@ import { EnabledTimelines } from '~/src/types/enabledTimelines'
import { Menu as MenuPreferences } from '~/src/types/preference'
import { LocalMarker } from '~/src/types/localMarker'
import Marker from './marker'
+import newDB from './database'
/**
* Context menu
@@ -141,12 +142,9 @@ unreadNotification.initialize().catch((err: Error) => log.error(err))
const preferencesDBPath = process.env.NODE_ENV === 'production' ? userData + './db/preferences.json' : 'preferences.json'
-const markerDBPath = process.env.NODE_ENV === 'production' ? userData + '/db/marker.db' : 'marker.db'
-const markerDB = new Datastore({
- filename: markerDBPath,
- autoload: true
-})
-const markerRepo = new Marker(markerDB)
+const lokiDatabasePath = process.env.NODE_ENV === 'production' ? userData + '/db/lokiDatabase.db' : 'lokiDatabase.db'
+
+let markerRepo: Marker | null = null
/**
* Cache path
@@ -257,6 +255,11 @@ const updateDockMenu = async (accountsChange: Array)
}
async function createWindow() {
+ /**
+ DB
+ */
+ const lokiDB = await newDB(lokiDatabasePath)
+ markerRepo = new Marker(lokiDB)
/**
* List accounts
*/
@@ -1160,11 +1163,17 @@ ipcMain.handle('update-spellchecker-languages', async (_: IpcMainInvokeEvent, la
// marker
ipcMain.handle('get-home-marker', async (_: IpcMainInvokeEvent, ownerID: string) => {
+ if (markerRepo === null) {
+ return null
+ }
const marker = await markerRepo.get(ownerID, 'home')
return marker
})
ipcMain.handle('get-notifications-marker', async (_: IpcMainInvokeEvent, ownerID: string) => {
+ if (markerRepo === null) {
+ return null
+ }
const marker = await markerRepo.get(ownerID, 'notifications')
return marker
})
@@ -1175,6 +1184,9 @@ ipcMain.on(
if (marker.owner_id === null || marker.owner_id === undefined || marker.owner_id === '') {
return null
}
+ if (markerRepo === null) {
+ return null
+ }
const res = await markerRepo.save(marker)
return res
}
diff --git a/src/main/marker.ts b/src/main/marker.ts
index ef3d0c4c..a4cdf89e 100644
--- a/src/main/marker.ts
+++ b/src/main/marker.ts
@@ -1,21 +1,22 @@
import { isEmpty } from 'lodash'
-import Datastore from 'nedb'
+import Loki, { Collection } from 'lokijs'
import { LocalMarker } from '~/src/types/localMarker'
export default class Marker {
- private db: Datastore
+ private markers: Collection
- constructor(db: Datastore) {
- this.db = db
- this.db.persistence.setAutocompactionInterval(60000) // milliseconds
+ constructor(db: Loki) {
+ this.markers = db.getCollection('markers')
}
private insert(marker: LocalMarker): Promise {
return new Promise((resolve, reject) => {
- this.db.insert(marker, (err, doc) => {
- if (err) return reject(err)
+ try {
+ const doc: LocalMarker = this.markers.insert(marker)
resolve(doc)
- })
+ } catch (err) {
+ reject(err)
+ }
})
}
@@ -23,18 +24,20 @@ export default class Marker {
// @ts-ignore
return new Promise((resolve, reject) => {
// eslint-disable-line no-unused-vars
- this.db.update(
- {
- owner_id: marker.owner_id,
- timeline: marker.timeline
- },
- { $set: marker },
- { multi: false },
- err => {
- if (err) return reject(err)
- return this.get(marker.owner_id, marker.timeline)
- }
- )
+ try {
+ this.markers.findAndUpdate(
+ {
+ owner_id: { $eq: marker.owner_id },
+ timeline: { $eq: marker.timeline }
+ },
+ (item: LocalMarker) => {
+ item.last_read_id = marker.last_read_id
+ }
+ )
+ return this.get(marker.owner_id, marker.timeline)
+ } catch (err) {
+ reject(err)
+ }
})
}
@@ -47,21 +50,28 @@ export default class Marker {
public async get(owner_id: string, timeline: 'home' | 'notifications'): Promise {
return new Promise((resolve, reject) => {
- this.db.findOne({ owner_id: owner_id, timeline: timeline }, (err, doc) => {
- if (err) return reject(err)
+ try {
+ const doc: LocalMarker | null = this.markers.findOne({
+ owner_id: { $eq: owner_id },
+ timeline: { $eq: timeline }
+ })
resolve(doc)
- })
+ } catch (err) {
+ reject(err)
+ }
})
}
public async list(owner_id: string): Promise> {
return new Promise((resolve, reject) => {
- this.db
- .find({ owner_id: owner_id })
- .exec((err, docs) => {
- if (err) return reject(err)
- resolve(docs)
+ try {
+ const docs: Array = this.markers.find({
+ owner_id: { $eq: owner_id }
})
+ resolve(docs)
+ } catch (err) {
+ reject(err)
+ }
})
}
}
diff --git a/yarn.lock b/yarn.lock
index 1e3ba4e9..bcdb3710 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1592,6 +1592,11 @@
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.176.tgz#641150fc1cda36fbfa329de603bbb175d7ee20c0"
integrity sha512-xZmuPTa3rlZoIbtDUyJKZQimJV3bxCmzMIO2c9Pz9afyDro6kr7R79GwcB6mRhuoPmV2p1Vb66WOJH7F886WKQ==
+"@types/lokijs@^1.5.7":
+ version "1.5.7"
+ resolved "https://registry.yarnpkg.com/@types/lokijs/-/lokijs-1.5.7.tgz#5eb4b189149681a89acad6dc8adb088f6025feb3"
+ integrity sha512-WEFQLgO3u2Wa7yFybqkTZYumqF1GcHvUwx8Tv2SUHy2qpnIainMMoLmEUGdjhPNp/v5pyC9e91fSMC3mkxBIDw==
+
"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@@ -7920,6 +7925,11 @@ loglevel@^1.6.8:
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197"
integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==
+lokijs@^1.5.12:
+ version "1.5.12"
+ resolved "https://registry.yarnpkg.com/lokijs/-/lokijs-1.5.12.tgz#cb55b37009bdf09ee7952a6adddd555b893653a0"
+ integrity sha512-Q5ALD6JiS6xAUWCwX3taQmgwxyveCtIIuL08+ml0nHwT3k0S/GIFJN+Hd38b1qYIMaE5X++iqsqWVksz7SYW+Q==
+
longest@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"