diff --git a/deno.json b/deno.json index 33cb119c..430d46be 100644 --- a/deno.json +++ b/deno.json @@ -17,7 +17,7 @@ ], "tasks": { "start": "deno run -A --env-file --deny-read=.env packages/ditto/server.ts", - "dev": "deno run -A --env-file --deny-read=.env --watch packages/ditto/server.ts", + "dev": "deno run -A --env-file --watch packages/ditto/server.ts", "hook": "deno run --allow-read --allow-run --allow-write https://deno.land/x/deno_hooks@0.1.1/mod.ts", "db:export": "deno run -A --env-file --deny-read=.env scripts/db-export.ts", "db:import": "deno run -A --env-file --deny-read=.env scripts/db-import.ts", diff --git a/packages/ditto/controllers/api/instance.ts b/packages/ditto/controllers/api/instance.ts index 0e07f385..9f46c932 100644 --- a/packages/ditto/controllers/api/instance.ts +++ b/packages/ditto/controllers/api/instance.ts @@ -15,13 +15,52 @@ const features = [ 'v2_suggestions', ]; +const cache = (f: () => (number | undefined) | Promise, interval: number) => { + let lastCheck = Date.now(); + let value: number | undefined = undefined; + + return async () => { + const now = Date.now(); + if (value === null || now - lastCheck > interval) { + lastCheck = now; + value = await f(); + } + console.log('error', value); + return Number(value || 0); + } +} + const instanceV1Controller: AppController = async (c) => { - const { conf } = c.var; + const { conf, db } = c.var; const { host, protocol } = conf.url; const meta = await getInstanceMetadata(c.var); /** Protocol to use for WebSocket URLs, depending on the protocol of the `LOCAL_DOMAIN`. */ const wsProtocol = protocol === 'http:' ? 'ws:' : 'wss:'; + const MINS_10 = 10 * 60 * 1000; + + const userCount = cache(async () => { + return await db.kysely + .selectFrom('author_stats') + .where('nip05_domain', '=', host) + .select(({ fn }) => fn.count('pubkey').distinct().as('users')) + .executeTakeFirst().then(obj => obj?.users || 0); + }, MINS_10); + + const domainCount = cache(async () => { + return await db.kysely + .selectFrom('author_stats') + .select(({ fn }) => fn.count('nip05_domain').distinct().as('domains')) + .executeTakeFirst().then(obj => obj?.domains || 0); + }, MINS_10); + + const statusCount = cache(async () => { + return await db.kysely + .selectFrom('nostr_events') + .where('kind', '=', 1) + .select(({ fn }) => fn.countAll().as('events')) + .executeTakeFirst().then(obj => obj?.events || 0); + }, MINS_10); return c.json({ uri: host, @@ -58,9 +97,9 @@ const instanceV1Controller: AppController = async (c) => { }, languages: ['en'], stats: { - domain_count: 0, - status_count: 0, - user_count: 0, + domain_count: await domainCount(), + status_count: await statusCount(), + user_count: await userCount(), }, urls: { streaming_api: `${wsProtocol}//${host}`,