mirror of
https://github.com/aljazceru/ditto.git
synced 2026-01-25 16:24:20 +01:00
Remove SQLite support
This commit is contained in:
@@ -1,75 +1,66 @@
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
|
||||
import { NDatabaseSchema, NPostgresSchema } from '@nostrify/db';
|
||||
import { FileMigrationProvider, Kysely, Migrator } from 'kysely';
|
||||
|
||||
import { Conf } from '@/config.ts';
|
||||
import { DittoPglite } from '@/db/adapters/DittoPglite.ts';
|
||||
import { DittoPostgres } from '@/db/adapters/DittoPostgres.ts';
|
||||
import { DittoSQLite } from '@/db/adapters/DittoSQLite.ts';
|
||||
import { DittoTables } from '@/db/DittoTables.ts';
|
||||
|
||||
export type DittoDatabase = {
|
||||
dialect: 'sqlite';
|
||||
kysely: Kysely<DittoTables> & Kysely<NDatabaseSchema>;
|
||||
} | {
|
||||
dialect: 'postgres';
|
||||
kysely: Kysely<DittoTables> & Kysely<NPostgresSchema>;
|
||||
};
|
||||
|
||||
export class DittoDB {
|
||||
private static db: Promise<DittoDatabase> | undefined;
|
||||
private static kysely: Promise<Kysely<DittoTables>> | undefined;
|
||||
|
||||
static getInstance(): Promise<DittoDatabase> {
|
||||
if (!this.db) {
|
||||
this.db = this._getInstance();
|
||||
static getInstance(): Promise<Kysely<DittoTables>> {
|
||||
if (!this.kysely) {
|
||||
this.kysely = this._getInstance();
|
||||
}
|
||||
return this.db;
|
||||
return this.kysely;
|
||||
}
|
||||
|
||||
static async _getInstance(): Promise<DittoDatabase> {
|
||||
const result = {} as DittoDatabase;
|
||||
static async _getInstance(): Promise<Kysely<DittoTables>> {
|
||||
const { protocol } = new URL(Conf.databaseUrl);
|
||||
|
||||
switch (Conf.db.url.protocol) {
|
||||
case 'sqlite:':
|
||||
result.dialect = 'sqlite';
|
||||
result.kysely = await DittoSQLite.getInstance();
|
||||
break;
|
||||
case 'pglite:':
|
||||
result.dialect = 'postgres';
|
||||
result.kysely = await DittoPglite.getInstance();
|
||||
let kysely: Kysely<DittoTables>;
|
||||
|
||||
switch (protocol) {
|
||||
case 'file:':
|
||||
case 'memory:':
|
||||
kysely = await DittoPglite.getInstance();
|
||||
break;
|
||||
case 'postgres:':
|
||||
case 'postgresql:':
|
||||
result.dialect = 'postgres';
|
||||
result.kysely = await DittoPostgres.getInstance();
|
||||
kysely = await DittoPostgres.getInstance();
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unsupported database URL.');
|
||||
}
|
||||
|
||||
await this.migrate(result.kysely);
|
||||
await this.migrate(kysely);
|
||||
|
||||
return result;
|
||||
return kysely;
|
||||
}
|
||||
|
||||
static get poolSize(): number {
|
||||
if (Conf.db.dialect === 'postgres') {
|
||||
const { protocol } = new URL(Conf.databaseUrl);
|
||||
|
||||
if (['postgres:', 'postgresql:'].includes(protocol)) {
|
||||
return DittoPostgres.poolSize;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static get availableConnections(): number {
|
||||
if (Conf.db.dialect === 'postgres') {
|
||||
const { protocol } = new URL(Conf.databaseUrl);
|
||||
|
||||
if (['postgres:', 'postgresql:'].includes(protocol)) {
|
||||
return DittoPostgres.availableConnections;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Migrate the database to the latest version. */
|
||||
static async migrate(kysely: DittoDatabase['kysely']) {
|
||||
static async migrate(kysely: Kysely<DittoTables>) {
|
||||
const migrator = new Migrator({
|
||||
db: kysely,
|
||||
provider: new FileMigrationProvider({
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export interface DittoTables {
|
||||
import { NPostgresSchema } from '@nostrify/db';
|
||||
|
||||
export interface DittoTables extends NPostgresSchema {
|
||||
nip46_tokens: NIP46TokenRow;
|
||||
author_stats: AuthorStatsRow;
|
||||
event_stats: EventStatsRow;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { PGlite } from '@electric-sql/pglite';
|
||||
import { NPostgresSchema } from '@nostrify/db';
|
||||
import { PgliteDialect } from '@soapbox/kysely-pglite';
|
||||
import { Kysely } from 'kysely';
|
||||
|
||||
@@ -8,17 +7,17 @@ import { DittoTables } from '@/db/DittoTables.ts';
|
||||
import { KyselyLogger } from '@/db/KyselyLogger.ts';
|
||||
|
||||
export class DittoPglite {
|
||||
static db: Kysely<DittoTables> & Kysely<NPostgresSchema> | undefined;
|
||||
static db: Kysely<DittoTables> | undefined;
|
||||
|
||||
// deno-lint-ignore require-await
|
||||
static async getInstance(): Promise<Kysely<DittoTables> & Kysely<NPostgresSchema>> {
|
||||
static async getInstance(): Promise<Kysely<DittoTables>> {
|
||||
if (!this.db) {
|
||||
this.db = new Kysely({
|
||||
this.db = new Kysely<DittoTables>({
|
||||
dialect: new PgliteDialect({
|
||||
database: new PGlite(this.path),
|
||||
database: new PGlite(Conf.databaseUrl),
|
||||
}),
|
||||
log: KyselyLogger,
|
||||
}) as Kysely<DittoTables> & Kysely<NPostgresSchema>;
|
||||
}) as Kysely<DittoTables>;
|
||||
}
|
||||
|
||||
return this.db;
|
||||
@@ -31,26 +30,4 @@ export class DittoPglite {
|
||||
static get availableConnections(): number {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Get the relative or absolute path based on the `DATABASE_URL`. */
|
||||
static get path(): string | undefined {
|
||||
if (Conf.databaseUrl === 'pglite://:memory:') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { host, pathname } = Conf.db.url;
|
||||
|
||||
if (!pathname) return '';
|
||||
|
||||
// Get relative path.
|
||||
if (host === '') {
|
||||
return pathname;
|
||||
} else if (host === '.') {
|
||||
return pathname;
|
||||
} else if (host) {
|
||||
return host + pathname;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { NPostgresSchema } from '@nostrify/db';
|
||||
import {
|
||||
BinaryOperationNode,
|
||||
FunctionNode,
|
||||
@@ -18,17 +17,17 @@ import { DittoTables } from '@/db/DittoTables.ts';
|
||||
import { KyselyLogger } from '@/db/KyselyLogger.ts';
|
||||
|
||||
export class DittoPostgres {
|
||||
static db: Kysely<DittoTables> & Kysely<NPostgresSchema> | undefined;
|
||||
static kysely: Kysely<DittoTables> | undefined;
|
||||
static postgres?: postgres.Sql;
|
||||
|
||||
// deno-lint-ignore require-await
|
||||
static async getInstance(): Promise<Kysely<DittoTables> & Kysely<NPostgresSchema>> {
|
||||
static async getInstance(): Promise<Kysely<DittoTables>> {
|
||||
if (!this.postgres) {
|
||||
this.postgres = postgres(Conf.databaseUrl, { max: Conf.pg.poolSize });
|
||||
}
|
||||
|
||||
if (!this.db) {
|
||||
this.db = new Kysely({
|
||||
if (!this.kysely) {
|
||||
this.kysely = new Kysely<DittoTables>({
|
||||
dialect: {
|
||||
createAdapter() {
|
||||
return new PostgresAdapter();
|
||||
@@ -46,10 +45,10 @@ export class DittoPostgres {
|
||||
},
|
||||
},
|
||||
log: KyselyLogger,
|
||||
}) as Kysely<DittoTables> & Kysely<NPostgresSchema>;
|
||||
});
|
||||
}
|
||||
|
||||
return this.db;
|
||||
return this.kysely;
|
||||
}
|
||||
|
||||
static get poolSize() {
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
import { NDatabaseSchema } from '@nostrify/db';
|
||||
import { PolySqliteDialect } from '@soapbox/kysely-deno-sqlite';
|
||||
import { Kysely, sql } from 'kysely';
|
||||
|
||||
import { Conf } from '@/config.ts';
|
||||
import { DittoTables } from '@/db/DittoTables.ts';
|
||||
import { KyselyLogger } from '@/db/KyselyLogger.ts';
|
||||
import SqliteWorker from '@/workers/sqlite.ts';
|
||||
|
||||
export class DittoSQLite {
|
||||
static db: Kysely<DittoTables> & Kysely<NDatabaseSchema> | undefined;
|
||||
|
||||
static async getInstance(): Promise<Kysely<DittoTables> & Kysely<NDatabaseSchema>> {
|
||||
if (!this.db) {
|
||||
const sqliteWorker = new SqliteWorker();
|
||||
await sqliteWorker.open(this.path);
|
||||
|
||||
this.db = new Kysely({
|
||||
dialect: new PolySqliteDialect({
|
||||
database: sqliteWorker,
|
||||
}),
|
||||
log: KyselyLogger,
|
||||
}) as Kysely<DittoTables> & Kysely<NDatabaseSchema>;
|
||||
|
||||
// Set PRAGMA values.
|
||||
await Promise.all([
|
||||
sql`PRAGMA synchronous = normal`.execute(this.db),
|
||||
sql`PRAGMA temp_store = memory`.execute(this.db),
|
||||
sql`PRAGMA foreign_keys = ON`.execute(this.db),
|
||||
sql`PRAGMA auto_vacuum = FULL`.execute(this.db),
|
||||
sql`PRAGMA journal_mode = WAL`.execute(this.db),
|
||||
sql.raw(`PRAGMA mmap_size = ${Conf.sqlite.mmapSize}`).execute(this.db),
|
||||
]);
|
||||
}
|
||||
return this.db;
|
||||
}
|
||||
|
||||
/** Get the relative or absolute path based on the `DATABASE_URL`. */
|
||||
static get path() {
|
||||
if (Conf.databaseUrl === 'sqlite://:memory:') {
|
||||
return ':memory:';
|
||||
}
|
||||
|
||||
const { host, pathname } = Conf.db.url;
|
||||
|
||||
if (!pathname) return '';
|
||||
|
||||
// Get relative path.
|
||||
if (host === '') {
|
||||
return pathname;
|
||||
} else if (host === '.') {
|
||||
return pathname;
|
||||
} else if (host) {
|
||||
return host + pathname;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,8 @@
|
||||
import { Kysely, sql } from 'kysely';
|
||||
import { Kysely } from 'kysely';
|
||||
|
||||
import { Conf } from '@/config.ts';
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
if (Conf.db.dialect === 'sqlite') {
|
||||
await sql`CREATE VIRTUAL TABLE events_fts USING fts5(id, content)`.execute(db);
|
||||
}
|
||||
export async function up(_db: Kysely<any>): Promise<void> {
|
||||
// This migration used to create an FTS table for SQLite, but SQLite support was removed.
|
||||
}
|
||||
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await db.schema.dropTable('events_fts').ifExists().execute();
|
||||
export async function down(_db: Kysely<any>): Promise<void> {
|
||||
}
|
||||
|
||||
@@ -1,25 +1,13 @@
|
||||
import { Kysely, sql } from 'kysely';
|
||||
|
||||
import { Conf } from '@/config.ts';
|
||||
import { Kysely } from 'kysely';
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await db.schema.alterTable('events').renameTo('nostr_events').execute();
|
||||
await db.schema.alterTable('tags').renameTo('nostr_tags').execute();
|
||||
await db.schema.alterTable('nostr_tags').renameColumn('tag', 'name').execute();
|
||||
|
||||
if (Conf.db.dialect === 'sqlite') {
|
||||
await db.schema.dropTable('events_fts').execute();
|
||||
await sql`CREATE VIRTUAL TABLE nostr_fts5 USING fts5(event_id, content)`.execute(db);
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await db.schema.alterTable('nostr_events').renameTo('events').execute();
|
||||
await db.schema.alterTable('nostr_tags').renameTo('tags').execute();
|
||||
await db.schema.alterTable('tags').renameColumn('name', 'tag').execute();
|
||||
|
||||
if (Conf.db.dialect === 'sqlite') {
|
||||
await db.schema.dropTable('nostr_fts5').execute();
|
||||
await sql`CREATE VIRTUAL TABLE events_fts USING fts5(id, content)`.execute(db);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user