From ebc0250d81f74bd25e741e2d588f5b44a75af6f9 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 11 Sep 2024 13:23:06 -0500 Subject: [PATCH] DittoDB.getInstance() -> Storages.kysely() --- scripts/db-migrate.ts | 4 ++-- scripts/stats-recompute.ts | 3 +-- src/controllers/api/oauth.ts | 3 +-- src/controllers/api/statuses.ts | 3 +-- src/controllers/api/streaming.ts | 3 +-- src/controllers/metrics.ts | 4 ++-- src/db/DittoDB.ts | 12 ------------ src/middleware/signerMiddleware.ts | 4 ++-- src/pipeline.ts | 9 ++++----- src/storages.ts | 17 ++++++++++++++++- src/storages/hydrate.ts | 6 +++--- src/trends.ts | 4 ++-- 12 files changed, 35 insertions(+), 37 deletions(-) diff --git a/scripts/db-migrate.ts b/scripts/db-migrate.ts index 0e1d694d..d3e93783 100644 --- a/scripts/db-migrate.ts +++ b/scripts/db-migrate.ts @@ -1,7 +1,7 @@ -import { DittoDB } from '@/db/DittoDB.ts'; +import { Storages } from '@/storages.ts'; // This migrates kysely internally. -const { kysely } = await DittoDB.getInstance(); +const kysely = await Storages.kysely(); // Close the connection before exiting. await kysely.destroy(); diff --git a/scripts/stats-recompute.ts b/scripts/stats-recompute.ts index 7d6f721f..77be13fe 100644 --- a/scripts/stats-recompute.ts +++ b/scripts/stats-recompute.ts @@ -1,6 +1,5 @@ import { nip19 } from 'nostr-tools'; -import { DittoDB } from '@/db/DittoDB.ts'; import { Storages } from '@/storages.ts'; import { refreshAuthorStats } from '@/utils/stats.ts'; @@ -18,6 +17,6 @@ try { } const store = await Storages.db(); -const { kysely } = await DittoDB.getInstance(); +const kysely = await Storages.kysely(); await refreshAuthorStats({ pubkey, kysely, store }); diff --git a/src/controllers/api/oauth.ts b/src/controllers/api/oauth.ts index a736f5ca..94aaeecd 100644 --- a/src/controllers/api/oauth.ts +++ b/src/controllers/api/oauth.ts @@ -6,7 +6,6 @@ import { z } from 'zod'; import { AppController } from '@/app.ts'; import { Conf } from '@/config.ts'; -import { DittoDB } from '@/db/DittoDB.ts'; import { nostrNow } from '@/utils.ts'; import { parseBody } from '@/utils/api.ts'; import { Storages } from '@/storages.ts'; @@ -82,7 +81,7 @@ const createTokenController: AppController = async (c) => { async function getToken( { pubkey, secret, relays = [] }: { pubkey: string; secret?: string; relays?: string[] }, ): Promise<`token1${string}`> { - const { kysely } = await DittoDB.getInstance(); + const kysely = await Storages.kysely(); const token = generateToken(); const serverSeckey = generateSecretKey(); diff --git a/src/controllers/api/statuses.ts b/src/controllers/api/statuses.ts index bef98122..e0956e74 100644 --- a/src/controllers/api/statuses.ts +++ b/src/controllers/api/statuses.ts @@ -8,7 +8,6 @@ import { z } from 'zod'; import { type AppController } from '@/app.ts'; import { Conf } from '@/config.ts'; -import { DittoDB } from '@/db/DittoDB.ts'; import { DittoUpload, dittoUploads } from '@/DittoUploads.ts'; import { DittoEvent } from '@/interfaces/DittoEvent.ts'; import { getAncestors, getAuthor, getDescendants, getEvent } from '@/queries.ts'; @@ -579,7 +578,7 @@ const zappedByController: AppController = async (c) => { const id = c.req.param('id'); const params = c.get('listPagination'); const store = await Storages.db(); - const { kysely } = await DittoDB.getInstance(); + const kysely = await Storages.kysely(); const zaps = await kysely.selectFrom('event_zaps') .selectAll() diff --git a/src/controllers/api/streaming.ts b/src/controllers/api/streaming.ts index 047aa573..cfa8c3c5 100644 --- a/src/controllers/api/streaming.ts +++ b/src/controllers/api/streaming.ts @@ -4,7 +4,6 @@ import { z } from 'zod'; import { type AppController } from '@/app.ts'; import { Conf } from '@/config.ts'; -import { DittoDB } from '@/db/DittoDB.ts'; import { streamingConnectionsGauge } from '@/metrics.ts'; import { MuteListPolicy } from '@/policies/MuteListPolicy.ts'; import { getFeedPubkeys } from '@/queries.ts'; @@ -222,7 +221,7 @@ async function topicToFilter( async function getTokenPubkey(token: string): Promise { if (token.startsWith('token1')) { - const { kysely } = await DittoDB.getInstance(); + const kysely = await Storages.kysely(); const { user_pubkey } = await kysely .selectFrom('nip46_tokens') diff --git a/src/controllers/metrics.ts b/src/controllers/metrics.ts index e25522ff..4ef378a0 100644 --- a/src/controllers/metrics.ts +++ b/src/controllers/metrics.ts @@ -1,12 +1,12 @@ import { register } from 'prom-client'; import { AppController } from '@/app.ts'; -import { DittoDB } from '@/db/DittoDB.ts'; import { dbAvailableConnectionsGauge, dbPoolSizeGauge } from '@/metrics.ts'; +import { Storages } from '@/storages.ts'; /** Prometheus/OpenMetrics controller. */ export const metricsController: AppController = async (c) => { - const db = await DittoDB.getInstance(); + const db = await Storages.database(); // Update some metrics at request time. dbPoolSizeGauge.set(db.poolSize); diff --git a/src/db/DittoDB.ts b/src/db/DittoDB.ts index 63d2bfb1..445c3da2 100644 --- a/src/db/DittoDB.ts +++ b/src/db/DittoDB.ts @@ -3,24 +3,12 @@ import path from 'node:path'; 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 { DittoDatabase, DittoDatabaseOpts } from '@/db/DittoDatabase.ts'; import { DittoTables } from '@/db/DittoTables.ts'; export class DittoDB { - private static db: DittoDatabase | undefined; - - /** Create (and migrate) the database if it isn't been already, or return the existing connection. */ - static async getInstance(): Promise { - if (!this.db) { - this.db = this.create(Conf.databaseUrl, { poolSize: Conf.pg.poolSize }); - await this.migrate(this.db.kysely); - } - return this.db; - } - /** Open a new database connection. */ static create(databaseUrl: string, opts?: DittoDatabaseOpts): DittoDatabase { const { protocol } = new URL(databaseUrl); diff --git a/src/middleware/signerMiddleware.ts b/src/middleware/signerMiddleware.ts index 60826db9..344e14ef 100644 --- a/src/middleware/signerMiddleware.ts +++ b/src/middleware/signerMiddleware.ts @@ -5,7 +5,7 @@ import { nip19 } from 'nostr-tools'; import { AppMiddleware } from '@/app.ts'; import { ConnectSigner } from '@/signers/ConnectSigner.ts'; import { ReadOnlySigner } from '@/signers/ReadOnlySigner.ts'; -import { DittoDB } from '@/db/DittoDB.ts'; +import { Storages } from '@/storages.ts'; /** We only accept "Bearer" type. */ const BEARER_REGEX = new RegExp(`^Bearer (${nip19.BECH32_REGEX.source})$`); @@ -20,7 +20,7 @@ export const signerMiddleware: AppMiddleware = async (c, next) => { if (bech32.startsWith('token1')) { try { - const { kysely } = await DittoDB.getInstance(); + const kysely = await Storages.kysely(); const { user_pubkey, server_seckey, relays } = await kysely .selectFrom('nip46_tokens') diff --git a/src/pipeline.ts b/src/pipeline.ts index dd59cb8d..88e5f29b 100644 --- a/src/pipeline.ts +++ b/src/pipeline.ts @@ -5,7 +5,6 @@ import { LRUCache } from 'lru-cache'; import { z } from 'zod'; import { Conf } from '@/config.ts'; -import { DittoDB } from '@/db/DittoDB.ts'; import { DittoEvent } from '@/interfaces/DittoEvent.ts'; import { pipelineEventsCounter, policyEventsCounter } from '@/metrics.ts'; import { RelayError } from '@/RelayError.ts'; @@ -53,7 +52,7 @@ async function handleEvent(event: DittoEvent, signal: AbortSignal): Promise { async function hydrateEvent(event: DittoEvent, signal: AbortSignal): Promise { await hydrateEvents({ events: [event], store: await Storages.db(), signal }); - const { kysely } = await DittoDB.getInstance(); + const kysely = await Storages.kysely(); const domain = await kysely .selectFrom('pubkey_domains') .select('domain') @@ -118,7 +117,7 @@ async function hydrateEvent(event: DittoEvent, signal: AbortSignal): Promise { if (NKinds.ephemeral(event.kind)) return; const store = await Storages.db(); - const { kysely } = await DittoDB.getInstance(); + const kysely = await Storages.kysely(); await updateStats({ event, store, kysely }).catch(debug); await store.event(event, { signal }); @@ -146,7 +145,7 @@ async function parseMetadata(event: NostrEvent, signal: AbortSignal): Promise | undefined; + private static _database: DittoDatabase | undefined; private static _admin: Promise | undefined; private static _client: Promise | undefined; private static _pubsub: Promise | undefined; private static _search: Promise | undefined; + public static async database(): Promise { + if (!this._database) { + this._database = DittoDB.create(Conf.databaseUrl, { poolSize: Conf.pg.poolSize }); + await DittoDB.migrate(this._database.kysely); + } + return this._database; + } + + public static async kysely(): Promise { + const { kysely } = await this.database(); + return kysely; + } + /** SQL database to store events this Ditto server cares about. */ public static async db(): Promise { if (!this._db) { this._db = (async () => { - const { kysely } = await DittoDB.getInstance(); + const { kysely } = await this.database(); const store = new EventsDB({ kysely, pubkey: Conf.pubkey, timeout: Conf.db.timeouts.default }); await seedZapSplits(store); return store; diff --git a/src/storages/hydrate.ts b/src/storages/hydrate.ts index c7a277c7..7b11cfb8 100644 --- a/src/storages/hydrate.ts +++ b/src/storages/hydrate.ts @@ -1,13 +1,13 @@ import { NStore } from '@nostrify/nostrify'; +import { Kysely } from 'kysely'; import { matchFilter } from 'nostr-tools'; -import { DittoDB } from '@/db/DittoDB.ts'; import { DittoTables } from '@/db/DittoTables.ts'; import { Conf } from '@/config.ts'; import { type DittoEvent } from '@/interfaces/DittoEvent.ts'; import { findQuoteTag } from '@/utils/tags.ts'; import { findQuoteInContent } from '@/utils/note.ts'; -import { Kysely } from 'kysely'; +import { Storages } from '@/storages.ts'; interface HydrateOpts { events: DittoEvent[]; @@ -18,7 +18,7 @@ interface HydrateOpts { /** Hydrate events using the provided storage. */ async function hydrateEvents(opts: HydrateOpts): Promise { - const { events, store, signal, kysely = (await DittoDB.getInstance()).kysely } = opts; + const { events, store, signal, kysely = await Storages.kysely() } = opts; if (!events.length) { return events; diff --git a/src/trends.ts b/src/trends.ts index 337ee5c7..de91a33d 100644 --- a/src/trends.ts +++ b/src/trends.ts @@ -3,10 +3,10 @@ import { Stickynotes } from '@soapbox/stickynotes'; import { Kysely, sql } from 'kysely'; import { Conf } from '@/config.ts'; -import { DittoDB } from '@/db/DittoDB.ts'; import { DittoTables } from '@/db/DittoTables.ts'; import { handleEvent } from '@/pipeline.ts'; import { AdminSigner } from '@/signers/AdminSigner.ts'; +import { Storages } from '@/storages.ts'; import { Time } from '@/utils/time.ts'; const console = new Stickynotes('ditto:trends'); @@ -70,7 +70,7 @@ export async function updateTrendingTags( aliases?: string[], ) { console.info(`Updating trending ${l}...`); - const { kysely } = await DittoDB.getInstance(); + const kysely = await Storages.kysely(); const signal = AbortSignal.timeout(1000); const yesterday = Math.floor((Date.now() - Time.days(1)) / 1000);