diff --git a/src/db.ts b/src/db.ts index 152b198b..7125f136 100644 --- a/src/db.ts +++ b/src/db.ts @@ -1,93 +1,10 @@ import fs from 'node:fs/promises'; import path from 'node:path'; -import { FileMigrationProvider, Kysely, Migrator, PolySqliteDialect } from '@/deps.ts'; -import { Conf } from '@/config.ts'; -import { setPragma } from '@/pragma.ts'; -import SqliteWorker from '@/workers/sqlite.ts'; +import { DittoDB } from '@/db/DittoDB.ts'; +import { FileMigrationProvider, Migrator } from '@/deps.ts'; -interface DittoDB { - events: EventRow; - events_fts: EventFTSRow; - tags: TagRow; - relays: RelayRow; - unattached_media: UnattachedMediaRow; - author_stats: AuthorStatsRow; - event_stats: EventStatsRow; - pubkey_domains: PubkeyDomainRow; -} - -interface AuthorStatsRow { - pubkey: string; - followers_count: number; - following_count: number; - notes_count: number; -} - -interface EventStatsRow { - event_id: string; - replies_count: number; - reposts_count: number; - reactions_count: number; -} - -interface EventRow { - id: string; - kind: number; - pubkey: string; - content: string; - created_at: number; - tags: string; - sig: string; - deleted_at: number | null; -} - -interface EventFTSRow { - id: string; - content: string; -} - -interface TagRow { - tag: string; - value: string; - event_id: string; -} - -interface RelayRow { - url: string; - domain: string; - active: boolean; -} - -interface UnattachedMediaRow { - id: string; - pubkey: string; - url: string; - data: string; - uploaded_at: Date; -} - -interface PubkeyDomainRow { - pubkey: string; - domain: string; - last_updated_at: number; -} - -const sqliteWorker = new SqliteWorker(); -await sqliteWorker.open(Conf.dbPath); - -const db = new Kysely({ - dialect: new PolySqliteDialect({ - database: sqliteWorker, - }), -}); - -// Set PRAGMA values. -await Promise.all([ - setPragma(db, 'synchronous', 'normal'), - setPragma(db, 'temp_store', 'memory'), - setPragma(db, 'mmap_size', Conf.sqlite.mmapSize), -]); +const db = await DittoDB.getInstance(); const migrator = new Migrator({ db, @@ -120,4 +37,4 @@ async function migrate() { await migrate(); -export { type AuthorStatsRow, db, type DittoDB, type EventRow, type EventStatsRow, type TagRow }; +export { db }; diff --git a/src/db/DittoDB.ts b/src/db/DittoDB.ts index e86b7e39..794a2284 100644 --- a/src/db/DittoDB.ts +++ b/src/db/DittoDB.ts @@ -14,4 +14,4 @@ export class DittoDB { throw new Error('Unsupported database URL.'); } } -} \ No newline at end of file +} diff --git a/src/stats.ts b/src/stats.ts index 0d6c8e8f..979dd475 100644 --- a/src/stats.ts +++ b/src/stats.ts @@ -1,10 +1,11 @@ -import { type AuthorStatsRow, db, type DittoDB, type EventStatsRow } from '@/db.ts'; +import { db } from '@/db.ts'; +import { DittoTables } from '@/db/DittoTables.ts'; import { Debug, type InsertQueryBuilder, type NostrEvent } from '@/deps.ts'; import { eventsDB } from '@/storages.ts'; import { findReplyTag } from '@/tags.ts'; -type AuthorStat = keyof Omit; -type EventStat = keyof Omit; +type AuthorStat = keyof Omit; +type EventStat = keyof Omit; type AuthorStatDiff = ['author_stats', pubkey: string, stat: AuthorStat, diff: number]; type EventStatDiff = ['event_stats', eventId: string, stat: EventStat, diff: number]; @@ -15,7 +16,7 @@ const debug = Debug('ditto:stats'); /** Store stats for the event in LMDB. */ async function updateStats(event: NostrEvent) { let prev: NostrEvent | undefined; - const queries: InsertQueryBuilder[] = []; + const queries: InsertQueryBuilder[] = []; // Kind 3 is a special case - replace the count with the new list. if (event.kind === 3) { @@ -98,8 +99,8 @@ async function getStatsDiff(event: NostrEvent, prev: NostrEvent | undefined): Pr /** Create an author stats query from the list of diffs. */ function authorStatsQuery(diffs: AuthorStatDiff[]) { - const values: AuthorStatsRow[] = diffs.map(([_, pubkey, stat, diff]) => { - const row: AuthorStatsRow = { + const values: DittoTables['author_stats'][] = diffs.map(([_, pubkey, stat, diff]) => { + const row: DittoTables['author_stats'] = { pubkey, followers_count: 0, following_count: 0, @@ -124,8 +125,8 @@ function authorStatsQuery(diffs: AuthorStatDiff[]) { /** Create an event stats query from the list of diffs. */ function eventStatsQuery(diffs: EventStatDiff[]) { - const values: EventStatsRow[] = diffs.map(([_, event_id, stat, diff]) => { - const row: EventStatsRow = { + const values: DittoTables['event_stats'][] = diffs.map(([_, event_id, stat, diff]) => { + const row: DittoTables['event_stats'] = { event_id, replies_count: 0, reposts_count: 0, diff --git a/src/storages/events-db.ts b/src/storages/events-db.ts index 22d08a9b..80bed752 100644 --- a/src/storages/events-db.ts +++ b/src/storages/events-db.ts @@ -1,6 +1,6 @@ import { NIP50, NostrFilter } from '@soapbox/nspec'; import { Conf } from '@/config.ts'; -import { type DittoDB } from '@/db.ts'; +import { DittoTables } from '@/db/DittoTables.ts'; import { Debug, Kysely, type NostrEvent, type NStore, type NStoreOpts, type SelectQueryBuilder } from '@/deps.ts'; import { normalizeFilters } from '@/filter.ts'; import { DittoEvent } from '@/interfaces/DittoEvent.ts'; @@ -33,7 +33,7 @@ const tagConditions: Record = { 'role': ({ event, count }) => event.kind === 30361 && count === 0, }; -type EventQuery = SelectQueryBuilder; + #db: Kysely; #debug = Debug('ditto:db:events'); - constructor(db: Kysely) { + constructor(db: Kysely) { this.#db = db; } @@ -143,7 +143,7 @@ class EventsDB implements NStore { } /** Build the query for a filter. */ - getFilterQuery(db: Kysely, filter: NostrFilter): EventQuery { + getFilterQuery(db: Kysely, filter: NostrFilter): EventQuery { let query = db .selectFrom('events') .select([ @@ -315,7 +315,7 @@ class EventsDB implements NStore { } /** Delete events from each table. Should be run in a transaction! */ - async deleteEventsTrx(db: Kysely, filters: NostrFilter[]) { + async deleteEventsTrx(db: Kysely, filters: NostrFilter[]) { if (!filters.length) return Promise.resolve(); this.#debug('DELETE', JSON.stringify(filters));