mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-24 07:29:30 +01:00
core: lazily use db in config & kv stores
This commit is contained in:
@@ -79,6 +79,7 @@ import { Sanitizer } from "../database/sanitizer.js";
|
||||
import { createTriggers, dropTriggers } from "../database/triggers.js";
|
||||
import { NNMigrationProvider } from "../database/migrations.js";
|
||||
import { ConfigStorage } from "../database/config.js";
|
||||
import { LazyPromise } from "../utils/lazy-promise.js";
|
||||
|
||||
type EventSourceConstructor = new (
|
||||
uri: string,
|
||||
@@ -101,6 +102,9 @@ class Database {
|
||||
sseMutex = new Mutex();
|
||||
_fs?: FileStorage;
|
||||
_compressor?: Promise<ICompressor>;
|
||||
private databaseReady = new LazyPromise<
|
||||
Kysely<DatabaseSchema> | Transaction<DatabaseSchema>
|
||||
>();
|
||||
|
||||
storage: StorageAccessor = () => {
|
||||
if (!this.options?.storage)
|
||||
@@ -148,11 +152,12 @@ class Database {
|
||||
return this._sql;
|
||||
};
|
||||
|
||||
private _kv?: KVStorage;
|
||||
kv: KVStorageAccessor = () => this._kv || new KVStorage(this.sql);
|
||||
private _config?: ConfigStorage;
|
||||
config: ConfigStorageAccessor = () =>
|
||||
this._config || new ConfigStorage(this.sql);
|
||||
private _kv = new KVStorage(this.databaseReady.promise);
|
||||
kv: KVStorageAccessor = () => this._kv;
|
||||
private _config: ConfigStorage = new ConfigStorage(
|
||||
this.databaseReady.promise
|
||||
);
|
||||
config: ConfigStorageAccessor = () => this._config;
|
||||
|
||||
private _transaction?: QueueValue<Transaction<DatabaseSchema>>;
|
||||
transaction = async (
|
||||
@@ -291,6 +296,7 @@ class Database {
|
||||
migrationProvider: new NNMigrationProvider(),
|
||||
onInit: (db) => this.onInit(db)
|
||||
})) as unknown as Kysely<DatabaseSchema>;
|
||||
this.databaseReady.resolve(this._sql);
|
||||
|
||||
await this.sanitizer.init();
|
||||
|
||||
|
||||
@@ -17,41 +17,47 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { DatabaseAccessor, RawDatabaseSchema } from "./index.js";
|
||||
import { LazyDatabaseAccessor, RawDatabaseSchema } from "./index.js";
|
||||
|
||||
export class ConfigStorage {
|
||||
private readonly db: DatabaseAccessor<RawDatabaseSchema>;
|
||||
constructor(db: DatabaseAccessor) {
|
||||
this.db = db as unknown as DatabaseAccessor<RawDatabaseSchema>;
|
||||
private readonly db: LazyDatabaseAccessor<RawDatabaseSchema>;
|
||||
constructor(db: LazyDatabaseAccessor) {
|
||||
this.db = db as unknown as LazyDatabaseAccessor<RawDatabaseSchema>;
|
||||
}
|
||||
|
||||
async getItem(name: string): Promise<unknown | undefined> {
|
||||
const result = await this.db()
|
||||
.selectFrom("config")
|
||||
.where("name", "==", name)
|
||||
.select("value")
|
||||
.limit(1)
|
||||
.executeTakeFirst();
|
||||
const result = await this.db.then((db) =>
|
||||
db
|
||||
.selectFrom("config")
|
||||
.where("name", "==", name)
|
||||
.select("value")
|
||||
.limit(1)
|
||||
.executeTakeFirst()
|
||||
);
|
||||
if (!result?.value) return;
|
||||
return JSON.parse(result.value);
|
||||
}
|
||||
|
||||
async setItem(name: string, value: unknown) {
|
||||
await this.db()
|
||||
.replaceInto("config")
|
||||
.values({
|
||||
name,
|
||||
value: JSON.stringify(value),
|
||||
dateModified: Date.now()
|
||||
})
|
||||
.execute();
|
||||
await this.db.then((db) =>
|
||||
db
|
||||
.replaceInto("config")
|
||||
.values({
|
||||
name,
|
||||
value: JSON.stringify(value),
|
||||
dateModified: Date.now()
|
||||
})
|
||||
.execute()
|
||||
);
|
||||
}
|
||||
|
||||
async removeItem(name: string) {
|
||||
await this.db().deleteFrom("config").where("name", "==", name).execute();
|
||||
await this.db.then((db) =>
|
||||
db.deleteFrom("config").where("name", "==", name).execute()
|
||||
);
|
||||
}
|
||||
|
||||
async clear() {
|
||||
await this.db().deleteFrom("config").execute();
|
||||
await this.db.then((db) => db.deleteFrom("config").execute());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,6 +198,10 @@ export type DatabaseAccessor<TSchema = DatabaseSchema> = () =>
|
||||
| Kysely<TSchema>
|
||||
| Transaction<TSchema>;
|
||||
|
||||
export type LazyDatabaseAccessor<TSchema = DatabaseSchema> = Promise<
|
||||
Kysely<TSchema> | Transaction<TSchema>
|
||||
>;
|
||||
|
||||
type FilterBooleanProperties<T, Type> = keyof {
|
||||
[K in keyof T as T[K] extends Type ? K : never]: T[K];
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { DatabaseAccessor, RawDatabaseSchema } from "./index.js";
|
||||
import { LazyDatabaseAccessor, RawDatabaseSchema } from "./index.js";
|
||||
import { Token } from "../api/token-manager.js";
|
||||
import { User } from "../types.js";
|
||||
|
||||
@@ -44,38 +44,44 @@ export const KEYS: (keyof KV)[] = [
|
||||
];
|
||||
|
||||
export class KVStorage {
|
||||
private readonly db: DatabaseAccessor<RawDatabaseSchema>;
|
||||
constructor(db: DatabaseAccessor) {
|
||||
this.db = db as unknown as DatabaseAccessor<RawDatabaseSchema>;
|
||||
private readonly db: LazyDatabaseAccessor<RawDatabaseSchema>;
|
||||
constructor(db: LazyDatabaseAccessor) {
|
||||
this.db = db as unknown as LazyDatabaseAccessor<RawDatabaseSchema>;
|
||||
}
|
||||
|
||||
async read<T extends keyof KV>(key: T): Promise<KV[T] | undefined> {
|
||||
const result = await this.db()
|
||||
.selectFrom("kv")
|
||||
.where("key", "==", key)
|
||||
.select("value")
|
||||
.limit(1)
|
||||
.executeTakeFirst();
|
||||
const result = await this.db.then((db) =>
|
||||
db
|
||||
.selectFrom("kv")
|
||||
.where("key", "==", key)
|
||||
.select("value")
|
||||
.limit(1)
|
||||
.executeTakeFirst()
|
||||
);
|
||||
if (!result?.value) return;
|
||||
return JSON.parse(result.value) as KV[T];
|
||||
}
|
||||
|
||||
async write<T extends keyof KV>(key: T, value: KV[T]) {
|
||||
await this.db()
|
||||
.replaceInto("kv")
|
||||
.values({
|
||||
key,
|
||||
value: JSON.stringify(value),
|
||||
dateModified: Date.now()
|
||||
})
|
||||
.execute();
|
||||
await this.db.then((db) =>
|
||||
db
|
||||
.replaceInto("kv")
|
||||
.values({
|
||||
key,
|
||||
value: JSON.stringify(value),
|
||||
dateModified: Date.now()
|
||||
})
|
||||
.execute()
|
||||
);
|
||||
}
|
||||
|
||||
async delete<T extends keyof KV>(key: T) {
|
||||
await this.db().deleteFrom("kv").where("key", "==", key).execute();
|
||||
await this.db.then((db) =>
|
||||
db.deleteFrom("kv").where("key", "==", key).execute()
|
||||
);
|
||||
}
|
||||
|
||||
async clear() {
|
||||
await this.db().deleteFrom("kv").execute();
|
||||
await this.db.then((db) => db.deleteFrom("kv").execute());
|
||||
}
|
||||
}
|
||||
|
||||
34
packages/core/src/utils/lazy-promise.ts
Normal file
34
packages/core/src/utils/lazy-promise.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export class LazyPromise<T> {
|
||||
private _promise: Promise<T>;
|
||||
private _resolve?: (result: T) => void;
|
||||
constructor() {
|
||||
this._promise = new Promise((resolve) => (this._resolve = resolve));
|
||||
}
|
||||
|
||||
resolve(result: T) {
|
||||
this._resolve?.(result);
|
||||
}
|
||||
|
||||
get promise() {
|
||||
return this._promise;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user