From 96fe8920cdacb2b27c6840a5179696b4a13213e6 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Fri, 12 Jul 2024 13:47:29 -0500 Subject: [PATCH] Make database timeouts configurable --- src/config.ts | 15 +++++++++++++++ src/controllers/api/accounts.ts | 2 +- src/controllers/api/notifications.ts | 2 +- src/controllers/api/timelines.ts | 2 +- src/controllers/nostr/relay.ts | 5 +++-- src/storages/EventsDB.ts | 8 ++++---- 6 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/config.ts b/src/config.ts index 1dd688b..33c233b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -98,6 +98,21 @@ class Conf { } return undefined; }, + /** Database query timeout configurations. */ + timeouts: { + /** Default query timeout when another setting isn't more specific. */ + get default(): number { + return Number(Deno.env.get('DB_TIMEOUT_DEFAULT') || 3_000); + }, + /** Timeout used for queries made through the Nostr relay. */ + get relay(): number { + return Number(Deno.env.get('DB_TIMEOUT_RELAY') || 1_000); + }, + /** Timeout used for timelines such as home, notifications, hashtag, etc. */ + get timelines(): number { + return Number(Deno.env.get('DB_TIMEOUT_TIMELINES') || 10_000); + }, + }, }; /** Character limit to enforce for posts made through Mastodon API. */ static get postCharLimit(): number { diff --git a/src/controllers/api/accounts.ts b/src/controllers/api/accounts.ts index ad4802c..460aa6d 100644 --- a/src/controllers/api/accounts.ts +++ b/src/controllers/api/accounts.ts @@ -209,7 +209,7 @@ const accountStatusesController: AppController = async (c) => { filter['#t'] = [tagged]; } - const opts = { signal, limit, timeout: 10_000 }; + const opts = { signal, limit, timeout: Conf.db.timeouts.timelines }; const events = await store.query([filter], opts) .then((events) => hydrateEvents({ events, store, signal })) diff --git a/src/controllers/api/notifications.ts b/src/controllers/api/notifications.ts index fab7c81..6f6036f 100644 --- a/src/controllers/api/notifications.ts +++ b/src/controllers/api/notifications.ts @@ -78,7 +78,7 @@ async function renderNotifications( const store = c.get('store'); const pubkey = await c.get('signer')?.getPublicKey()!; const { signal } = c.req.raw; - const opts = { signal, limit: params.limit, timeout: 15_000 }; + const opts = { signal, limit: params.limit, timeout: Conf.db.timeouts.timelines }; const events = await store .query(filters, opts) diff --git a/src/controllers/api/timelines.ts b/src/controllers/api/timelines.ts index 62f1cd2..848ae63 100644 --- a/src/controllers/api/timelines.ts +++ b/src/controllers/api/timelines.ts @@ -60,7 +60,7 @@ const suggestedTimelineController: AppController = async (c) => { async function renderStatuses(c: AppContext, filters: NostrFilter[]) { const { signal } = c.req.raw; const store = c.get('store'); - const opts = { signal, timeout: 10_000 }; + const opts = { signal, timeout: Conf.db.timeouts.timelines }; const events = await store .query(filters, opts) diff --git a/src/controllers/nostr/relay.ts b/src/controllers/nostr/relay.ts index f124360..02d2995 100644 --- a/src/controllers/nostr/relay.ts +++ b/src/controllers/nostr/relay.ts @@ -10,6 +10,7 @@ import { } from '@nostrify/nostrify'; import { AppController } from '@/app.ts'; +import { Conf } from '@/config.ts'; import { relayInfoController } from '@/controllers/nostr/relay-info.ts'; import { relayConnectionsGauge, relayEventCounter, relayMessageCounter } from '@/metrics.ts'; import * as pipeline from '@/pipeline.ts'; @@ -95,7 +96,7 @@ function connectStream(socket: WebSocket, ip: string | undefined) { const pubsub = await Storages.pubsub(); try { - for (const event of await store.query(filters, { limit: FILTER_LIMIT, timeout: 1000 })) { + for (const event of await store.query(filters, { limit: FILTER_LIMIT, timeout: Conf.db.timeouts.relay })) { send(['EVENT', subId, event]); } } catch (e) { @@ -150,7 +151,7 @@ function connectStream(socket: WebSocket, ip: string | undefined) { /** Handle COUNT. Return the number of events matching the filters. */ async function handleCount([_, subId, ...filters]: NostrClientCOUNT): Promise { const store = await Storages.db(); - const { count } = await store.count(filters, { timeout: 100 }); + const { count } = await store.count(filters, { timeout: Conf.db.timeouts.relay }); send(['COUNT', subId, { count, approximate: false }]); } diff --git a/src/storages/EventsDB.ts b/src/storages/EventsDB.ts index d66a65b..abf076c 100644 --- a/src/storages/EventsDB.ts +++ b/src/storages/EventsDB.ts @@ -64,7 +64,7 @@ class EventsDB implements NStore { await this.deleteEventsAdmin(event); try { - await this.store.event(event, { ...opts, timeout: opts.timeout ?? 1000 }); + await this.store.event(event, { ...opts, timeout: opts.timeout ?? Conf.db.timeouts.default }); } catch (e) { if (e.message === 'Cannot add a deleted event') { throw new RelayError('blocked', 'event deleted by user'); @@ -164,7 +164,7 @@ class EventsDB implements NStore { this.console.debug('REQ', JSON.stringify(filters)); - return this.store.query(filters, { ...opts, timeout: opts.timeout ?? 1000 }); + return this.store.query(filters, { ...opts, timeout: opts.timeout ?? Conf.db.timeouts.default }); } /** Delete events based on filters from the database. */ @@ -172,7 +172,7 @@ class EventsDB implements NStore { if (!filters.length) return Promise.resolve(); this.console.debug('DELETE', JSON.stringify(filters)); - return this.store.remove(filters, { ...opts, timeout: opts.timeout ?? 3000 }); + return this.store.remove(filters, { ...opts, timeout: opts.timeout ?? Conf.db.timeouts.default }); } /** Get number of events that would be returned by filters. */ @@ -185,7 +185,7 @@ class EventsDB implements NStore { this.console.debug('COUNT', JSON.stringify(filters)); - return this.store.count(filters, { ...opts, timeout: opts.timeout ?? 500 }); + return this.store.count(filters, { ...opts, timeout: opts.timeout ?? Conf.db.timeouts.default }); } /** Return only the tags that should be indexed. */