Rework Kysely db to be async
This commit is contained in:
parent
68b5887ed0
commit
a4226a963f
|
@ -24,6 +24,7 @@
|
||||||
"@sentry/deno": "https://deno.land/x/sentry@7.112.2/index.mjs",
|
"@sentry/deno": "https://deno.land/x/sentry@7.112.2/index.mjs",
|
||||||
"@soapbox/kysely-deno-sqlite": "jsr:@soapbox/kysely-deno-sqlite@^2.1.0",
|
"@soapbox/kysely-deno-sqlite": "jsr:@soapbox/kysely-deno-sqlite@^2.1.0",
|
||||||
"@soapbox/stickynotes": "jsr:@soapbox/stickynotes@^0.4.0",
|
"@soapbox/stickynotes": "jsr:@soapbox/stickynotes@^0.4.0",
|
||||||
|
"@std/assert": "jsr:@std/assert@^0.225.1",
|
||||||
"@std/cli": "jsr:@std/cli@^0.223.0",
|
"@std/cli": "jsr:@std/cli@^0.223.0",
|
||||||
"@std/crypto": "jsr:@std/crypto@^0.224.0",
|
"@std/crypto": "jsr:@std/crypto@^0.224.0",
|
||||||
"@std/dotenv": "jsr:@std/dotenv@^0.224.0",
|
"@std/dotenv": "jsr:@std/dotenv@^0.224.0",
|
||||||
|
|
41
src/db.ts
41
src/db.ts
|
@ -1,41 +0,0 @@
|
||||||
import fs from 'node:fs/promises';
|
|
||||||
import path from 'node:path';
|
|
||||||
|
|
||||||
import { FileMigrationProvider, Migrator } from 'kysely';
|
|
||||||
|
|
||||||
import { DittoDB } from '@/db/DittoDB.ts';
|
|
||||||
|
|
||||||
const db = await DittoDB.getInstance();
|
|
||||||
|
|
||||||
const migrator = new Migrator({
|
|
||||||
db,
|
|
||||||
provider: new FileMigrationProvider({
|
|
||||||
fs,
|
|
||||||
path,
|
|
||||||
migrationFolder: new URL(import.meta.resolve('./db/migrations')).pathname,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
/** Migrate the database to the latest version. */
|
|
||||||
async function migrate() {
|
|
||||||
console.info('Running migrations...');
|
|
||||||
const results = await migrator.migrateToLatest();
|
|
||||||
|
|
||||||
if (results.error) {
|
|
||||||
console.error(results.error);
|
|
||||||
Deno.exit(1);
|
|
||||||
} else {
|
|
||||||
if (!results.results?.length) {
|
|
||||||
console.info('Everything up-to-date.');
|
|
||||||
} else {
|
|
||||||
console.info('Migrations finished!');
|
|
||||||
for (const { migrationName, status } of results.results!) {
|
|
||||||
console.info(` - ${migrationName}: ${status}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await migrate();
|
|
||||||
|
|
||||||
export { db };
|
|
|
@ -1,4 +1,7 @@
|
||||||
import { Kysely } from 'kysely';
|
import fs from 'node:fs/promises';
|
||||||
|
import path from 'node:path';
|
||||||
|
|
||||||
|
import { FileMigrationProvider, Kysely, Migrator } from 'kysely';
|
||||||
|
|
||||||
import { Conf } from '@/config.ts';
|
import { Conf } from '@/config.ts';
|
||||||
import { DittoPostgres } from '@/db/adapters/DittoPostgres.ts';
|
import { DittoPostgres } from '@/db/adapters/DittoPostgres.ts';
|
||||||
|
@ -6,17 +9,63 @@ import { DittoSQLite } from '@/db/adapters/DittoSQLite.ts';
|
||||||
import { DittoTables } from '@/db/DittoTables.ts';
|
import { DittoTables } from '@/db/DittoTables.ts';
|
||||||
|
|
||||||
export class DittoDB {
|
export class DittoDB {
|
||||||
|
private static kysely: Promise<Kysely<DittoTables>> | undefined;
|
||||||
|
|
||||||
static getInstance(): Promise<Kysely<DittoTables>> {
|
static getInstance(): Promise<Kysely<DittoTables>> {
|
||||||
|
if (!this.kysely) {
|
||||||
|
this.kysely = this._getInstance();
|
||||||
|
}
|
||||||
|
return this.kysely;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async _getInstance(): Promise<Kysely<DittoTables>> {
|
||||||
const { databaseUrl } = Conf;
|
const { databaseUrl } = Conf;
|
||||||
|
|
||||||
|
let kysely: Kysely<DittoTables>;
|
||||||
|
|
||||||
switch (databaseUrl.protocol) {
|
switch (databaseUrl.protocol) {
|
||||||
case 'sqlite:':
|
case 'sqlite:':
|
||||||
return DittoSQLite.getInstance();
|
kysely = await DittoSQLite.getInstance();
|
||||||
|
break;
|
||||||
case 'postgres:':
|
case 'postgres:':
|
||||||
case 'postgresql:':
|
case 'postgresql:':
|
||||||
return DittoPostgres.getInstance();
|
kysely = await DittoPostgres.getInstance();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error('Unsupported database URL.');
|
throw new Error('Unsupported database URL.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.migrate(kysely);
|
||||||
|
|
||||||
|
return kysely;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Migrate the database to the latest version. */
|
||||||
|
private static async migrate(kysely: Kysely<DittoTables>) {
|
||||||
|
const migrator = new Migrator({
|
||||||
|
db: kysely,
|
||||||
|
provider: new FileMigrationProvider({
|
||||||
|
fs,
|
||||||
|
path,
|
||||||
|
migrationFolder: new URL(import.meta.resolve('../db/migrations')).pathname,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
console.info('Running migrations...');
|
||||||
|
const results = await migrator.migrateToLatest();
|
||||||
|
|
||||||
|
if (results.error) {
|
||||||
|
console.error(results.error);
|
||||||
|
Deno.exit(1);
|
||||||
|
} else {
|
||||||
|
if (!results.results?.length) {
|
||||||
|
console.info('Everything up-to-date.');
|
||||||
|
} else {
|
||||||
|
console.info('Migrations finished!');
|
||||||
|
for (const { migrationName, status } of results.results!) {
|
||||||
|
console.info(` - ${migrationName}: ${status}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import uuid62 from 'uuid62';
|
import uuid62 from 'uuid62';
|
||||||
|
|
||||||
import { db } from '@/db.ts';
|
import { DittoDB } from '@/db/DittoDB.ts';
|
||||||
import { type MediaData } from '@/schemas/nostr.ts';
|
import { type MediaData } from '@/schemas/nostr.ts';
|
||||||
|
|
||||||
interface UnattachedMedia {
|
interface UnattachedMedia {
|
||||||
|
@ -19,7 +19,8 @@ async function insertUnattachedMedia(media: Omit<UnattachedMedia, 'id' | 'upload
|
||||||
...media,
|
...media,
|
||||||
};
|
};
|
||||||
|
|
||||||
await db.insertInto('unattached_media')
|
const kysely = await DittoDB.getInstance();
|
||||||
|
await kysely.insertInto('unattached_media')
|
||||||
.values({ ...result, data: JSON.stringify(media.data) })
|
.values({ ...result, data: JSON.stringify(media.data) })
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
|
@ -27,8 +28,9 @@ async function insertUnattachedMedia(media: Omit<UnattachedMedia, 'id' | 'upload
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Select query for unattached media. */
|
/** Select query for unattached media. */
|
||||||
function selectUnattachedMediaQuery() {
|
async function selectUnattachedMediaQuery() {
|
||||||
return db.selectFrom('unattached_media')
|
const kysely = await DittoDB.getInstance();
|
||||||
|
return kysely.selectFrom('unattached_media')
|
||||||
.select([
|
.select([
|
||||||
'unattached_media.id',
|
'unattached_media.id',
|
||||||
'unattached_media.pubkey',
|
'unattached_media.pubkey',
|
||||||
|
@ -39,25 +41,27 @@ function selectUnattachedMediaQuery() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Find attachments that exist but aren't attached to any events. */
|
/** Find attachments that exist but aren't attached to any events. */
|
||||||
function getUnattachedMedia(until: Date) {
|
async function getUnattachedMedia(until: Date) {
|
||||||
return selectUnattachedMediaQuery()
|
const query = await selectUnattachedMediaQuery();
|
||||||
|
return query
|
||||||
.leftJoin('tags', 'unattached_media.url', 'tags.value')
|
.leftJoin('tags', 'unattached_media.url', 'tags.value')
|
||||||
.where('uploaded_at', '<', until.getTime())
|
.where('uploaded_at', '<', until.getTime())
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Delete unattached media by URL. */
|
/** Delete unattached media by URL. */
|
||||||
function deleteUnattachedMediaByUrl(url: string) {
|
async function deleteUnattachedMediaByUrl(url: string) {
|
||||||
return db.deleteFrom('unattached_media')
|
const kysely = await DittoDB.getInstance();
|
||||||
|
return kysely.deleteFrom('unattached_media')
|
||||||
.where('url', '=', url)
|
.where('url', '=', url)
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get unattached media by IDs. */
|
/** Get unattached media by IDs. */
|
||||||
// deno-lint-ignore require-await
|
|
||||||
async function getUnattachedMediaByIds(ids: string[]) {
|
async function getUnattachedMediaByIds(ids: string[]) {
|
||||||
if (!ids.length) return [];
|
if (!ids.length) return [];
|
||||||
return selectUnattachedMediaQuery()
|
const query = await selectUnattachedMediaQuery();
|
||||||
|
return query
|
||||||
.where('id', 'in', ids)
|
.where('id', 'in', ids)
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
@ -65,7 +69,8 @@ async function getUnattachedMediaByIds(ids: string[]) {
|
||||||
/** Delete rows as an event with media is being created. */
|
/** Delete rows as an event with media is being created. */
|
||||||
async function deleteAttachedMedia(pubkey: string, urls: string[]): Promise<void> {
|
async function deleteAttachedMedia(pubkey: string, urls: string[]): Promise<void> {
|
||||||
if (!urls.length) return;
|
if (!urls.length) return;
|
||||||
await db.deleteFrom('unattached_media')
|
const kysely = await DittoDB.getInstance();
|
||||||
|
await kysely.deleteFrom('unattached_media')
|
||||||
.where('pubkey', '=', pubkey)
|
.where('pubkey', '=', pubkey)
|
||||||
.where('url', 'in', urls)
|
.where('url', 'in', urls)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
|
@ -5,7 +5,7 @@ import Debug from '@soapbox/stickynotes/debug';
|
||||||
import { sql } from 'kysely';
|
import { sql } from 'kysely';
|
||||||
|
|
||||||
import { Conf } from '@/config.ts';
|
import { Conf } from '@/config.ts';
|
||||||
import { db } from '@/db.ts';
|
import { DittoDB } from '@/db/DittoDB.ts';
|
||||||
import { deleteAttachedMedia } from '@/db/unattached-media.ts';
|
import { deleteAttachedMedia } from '@/db/unattached-media.ts';
|
||||||
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||||
import { isEphemeralKind } from '@/kinds.ts';
|
import { isEphemeralKind } from '@/kinds.ts';
|
||||||
|
@ -91,7 +91,8 @@ async function encounterEvent(event: NostrEvent, signal: AbortSignal): Promise<b
|
||||||
async function hydrateEvent(event: DittoEvent, signal: AbortSignal): Promise<void> {
|
async function hydrateEvent(event: DittoEvent, signal: AbortSignal): Promise<void> {
|
||||||
await hydrateEvents({ events: [event], store: await Storages.db(), signal });
|
await hydrateEvents({ events: [event], store: await Storages.db(), signal });
|
||||||
|
|
||||||
const domain = await db
|
const kysely = await DittoDB.getInstance();
|
||||||
|
const domain = await kysely
|
||||||
.selectFrom('pubkey_domains')
|
.selectFrom('pubkey_domains')
|
||||||
.select('domain')
|
.select('domain')
|
||||||
.where('pubkey', '=', event.pubkey)
|
.where('pubkey', '=', event.pubkey)
|
||||||
|
@ -140,6 +141,7 @@ async function parseMetadata(event: NostrEvent, signal: AbortSignal): Promise<vo
|
||||||
|
|
||||||
// Track pubkey domain.
|
// Track pubkey domain.
|
||||||
try {
|
try {
|
||||||
|
const kysely = await DittoDB.getInstance();
|
||||||
const { domain } = parseNip05(nip05);
|
const { domain } = parseNip05(nip05);
|
||||||
|
|
||||||
await sql`
|
await sql`
|
||||||
|
@ -149,7 +151,7 @@ async function parseMetadata(event: NostrEvent, signal: AbortSignal): Promise<vo
|
||||||
domain = excluded.domain,
|
domain = excluded.domain,
|
||||||
last_updated_at = excluded.last_updated_at
|
last_updated_at = excluded.last_updated_at
|
||||||
WHERE excluded.last_updated_at > pubkey_domains.last_updated_at
|
WHERE excluded.last_updated_at > pubkey_domains.last_updated_at
|
||||||
`.execute(db);
|
`.execute(kysely);
|
||||||
} catch (_e) {
|
} catch (_e) {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
23
src/stats.ts
23
src/stats.ts
|
@ -2,7 +2,7 @@ import { NKinds, NostrEvent } from '@nostrify/nostrify';
|
||||||
import Debug from '@soapbox/stickynotes/debug';
|
import Debug from '@soapbox/stickynotes/debug';
|
||||||
import { InsertQueryBuilder } from 'kysely';
|
import { InsertQueryBuilder } from 'kysely';
|
||||||
|
|
||||||
import { db } from '@/db.ts';
|
import { DittoDB } from '@/db/DittoDB.ts';
|
||||||
import { DittoTables } from '@/db/DittoTables.ts';
|
import { DittoTables } from '@/db/DittoTables.ts';
|
||||||
import { Storages } from '@/storages.ts';
|
import { Storages } from '@/storages.ts';
|
||||||
import { findReplyTag } from '@/tags.ts';
|
import { findReplyTag } from '@/tags.ts';
|
||||||
|
@ -25,7 +25,7 @@ async function updateStats(event: NostrEvent) {
|
||||||
if (event.kind === 3) {
|
if (event.kind === 3) {
|
||||||
prev = await getPrevEvent(event);
|
prev = await getPrevEvent(event);
|
||||||
if (!prev || event.created_at >= prev.created_at) {
|
if (!prev || event.created_at >= prev.created_at) {
|
||||||
queries.push(updateFollowingCountQuery(event));
|
queries.push(await updateFollowingCountQuery(event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,8 +37,8 @@ async function updateStats(event: NostrEvent) {
|
||||||
debug(JSON.stringify({ id: event.id, pubkey: event.pubkey, kind: event.kind, tags: event.tags, statDiffs }));
|
debug(JSON.stringify({ id: event.id, pubkey: event.pubkey, kind: event.kind, tags: event.tags, statDiffs }));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pubkeyDiffs.length) queries.push(authorStatsQuery(pubkeyDiffs));
|
if (pubkeyDiffs.length) queries.push(await authorStatsQuery(pubkeyDiffs));
|
||||||
if (eventDiffs.length) queries.push(eventStatsQuery(eventDiffs));
|
if (eventDiffs.length) queries.push(await eventStatsQuery(eventDiffs));
|
||||||
|
|
||||||
if (queries.length) {
|
if (queries.length) {
|
||||||
await Promise.all(queries.map((query) => query.execute()));
|
await Promise.all(queries.map((query) => query.execute()));
|
||||||
|
@ -102,7 +102,7 @@ async function getStatsDiff(event: NostrEvent, prev: NostrEvent | undefined): Pr
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create an author stats query from the list of diffs. */
|
/** Create an author stats query from the list of diffs. */
|
||||||
function authorStatsQuery(diffs: AuthorStatDiff[]) {
|
async function authorStatsQuery(diffs: AuthorStatDiff[]) {
|
||||||
const values: DittoTables['author_stats'][] = diffs.map(([_, pubkey, stat, diff]) => {
|
const values: DittoTables['author_stats'][] = diffs.map(([_, pubkey, stat, diff]) => {
|
||||||
const row: DittoTables['author_stats'] = {
|
const row: DittoTables['author_stats'] = {
|
||||||
pubkey,
|
pubkey,
|
||||||
|
@ -114,7 +114,8 @@ function authorStatsQuery(diffs: AuthorStatDiff[]) {
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
|
|
||||||
return db.insertInto('author_stats')
|
const kysely = await DittoDB.getInstance();
|
||||||
|
return kysely.insertInto('author_stats')
|
||||||
.values(values)
|
.values(values)
|
||||||
.onConflict((oc) =>
|
.onConflict((oc) =>
|
||||||
oc
|
oc
|
||||||
|
@ -128,7 +129,7 @@ function authorStatsQuery(diffs: AuthorStatDiff[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create an event stats query from the list of diffs. */
|
/** Create an event stats query from the list of diffs. */
|
||||||
function eventStatsQuery(diffs: EventStatDiff[]) {
|
async function eventStatsQuery(diffs: EventStatDiff[]) {
|
||||||
const values: DittoTables['event_stats'][] = diffs.map(([_, event_id, stat, diff]) => {
|
const values: DittoTables['event_stats'][] = diffs.map(([_, event_id, stat, diff]) => {
|
||||||
const row: DittoTables['event_stats'] = {
|
const row: DittoTables['event_stats'] = {
|
||||||
event_id,
|
event_id,
|
||||||
|
@ -140,7 +141,8 @@ function eventStatsQuery(diffs: EventStatDiff[]) {
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
|
|
||||||
return db.insertInto('event_stats')
|
const kysely = await DittoDB.getInstance();
|
||||||
|
return kysely.insertInto('event_stats')
|
||||||
.values(values)
|
.values(values)
|
||||||
.onConflict((oc) =>
|
.onConflict((oc) =>
|
||||||
oc
|
oc
|
||||||
|
@ -167,14 +169,15 @@ async function getPrevEvent(event: NostrEvent): Promise<NostrEvent | undefined>
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the following count to the total number of unique "p" tags in the follow list. */
|
/** Set the following count to the total number of unique "p" tags in the follow list. */
|
||||||
function updateFollowingCountQuery({ pubkey, tags }: NostrEvent) {
|
async function updateFollowingCountQuery({ pubkey, tags }: NostrEvent) {
|
||||||
const following_count = new Set(
|
const following_count = new Set(
|
||||||
tags
|
tags
|
||||||
.filter(([name]) => name === 'p')
|
.filter(([name]) => name === 'p')
|
||||||
.map(([_, value]) => value),
|
.map(([_, value]) => value),
|
||||||
).size;
|
).size;
|
||||||
|
|
||||||
return db.insertInto('author_stats')
|
const kysely = await DittoDB.getInstance();
|
||||||
|
return kysely.insertInto('author_stats')
|
||||||
.values({
|
.values({
|
||||||
pubkey,
|
pubkey,
|
||||||
following_count,
|
following_count,
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// deno-lint-ignore-file require-await
|
// deno-lint-ignore-file require-await
|
||||||
import { NCache } from '@nostrify/nostrify';
|
import { NCache } from '@nostrify/nostrify';
|
||||||
|
|
||||||
import { Conf } from '@/config.ts';
|
import { Conf } from '@/config.ts';
|
||||||
import { db } from '@/db.ts';
|
import { DittoDB } from '@/db/DittoDB.ts';
|
||||||
import { EventsDB } from '@/storages/events-db.ts';
|
import { EventsDB } from '@/storages/events-db.ts';
|
||||||
import { Optimizer } from '@/storages/optimizer.ts';
|
import { Optimizer } from '@/storages/optimizer.ts';
|
||||||
import { PoolStore } from '@/storages/pool-store.ts';
|
import { PoolStore } from '@/storages/pool-store.ts';
|
||||||
|
@ -24,7 +25,10 @@ export class Storages {
|
||||||
/** SQLite database to store events this Ditto server cares about. */
|
/** SQLite database to store events this Ditto server cares about. */
|
||||||
public static async db(): Promise<EventsDB> {
|
public static async db(): Promise<EventsDB> {
|
||||||
if (!this._db) {
|
if (!this._db) {
|
||||||
this._db = Promise.resolve(new EventsDB(db));
|
this._db = (async () => {
|
||||||
|
const kysely = await DittoDB.getInstance();
|
||||||
|
return new EventsDB(kysely);
|
||||||
|
})();
|
||||||
}
|
}
|
||||||
return this._db;
|
return this._db;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import { db } from '@/db.ts';
|
import { assertEquals, assertRejects } from '@std/assert';
|
||||||
import { assertEquals, assertRejects } from '@/deps-test.ts';
|
|
||||||
|
import { DittoDB } from '@/db/DittoDB.ts';
|
||||||
|
|
||||||
import event0 from '~/fixtures/events/event-0.json' with { type: 'json' };
|
import event0 from '~/fixtures/events/event-0.json' with { type: 'json' };
|
||||||
import event1 from '~/fixtures/events/event-1.json' with { type: 'json' };
|
import event1 from '~/fixtures/events/event-1.json' with { type: 'json' };
|
||||||
|
|
||||||
import { EventsDB } from '@/storages/events-db.ts';
|
import { EventsDB } from '@/storages/events-db.ts';
|
||||||
|
|
||||||
const eventsDB = new EventsDB(db);
|
const kysely = await DittoDB.getInstance();
|
||||||
|
const eventsDB = new EventsDB(kysely);
|
||||||
|
|
||||||
Deno.test('count filters', async () => {
|
Deno.test('count filters', async () => {
|
||||||
assertEquals((await eventsDB.count([{ kinds: [1] }])).count, 0);
|
assertEquals((await eventsDB.count([{ kinds: [1] }])).count, 0);
|
||||||
|
@ -34,7 +36,7 @@ Deno.test('query events with domain search filter', async () => {
|
||||||
assertEquals(await eventsDB.query([{ search: 'domain:localhost:8000' }]), []);
|
assertEquals(await eventsDB.query([{ search: 'domain:localhost:8000' }]), []);
|
||||||
assertEquals(await eventsDB.query([{ search: '' }]), [event1]);
|
assertEquals(await eventsDB.query([{ search: '' }]), [event1]);
|
||||||
|
|
||||||
await db
|
await kysely
|
||||||
.insertInto('pubkey_domains')
|
.insertInto('pubkey_domains')
|
||||||
.values({ pubkey: event1.pubkey, domain: 'localhost:8000', last_updated_at: event1.created_at })
|
.values({ pubkey: event1.pubkey, domain: 'localhost:8000', last_updated_at: event1.created_at })
|
||||||
.execute();
|
.execute();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { NostrEvent, NStore } from '@nostrify/nostrify';
|
import { NostrEvent, NStore } from '@nostrify/nostrify';
|
||||||
import { matchFilter } from 'nostr-tools';
|
import { matchFilter } from 'nostr-tools';
|
||||||
|
|
||||||
import { db } from '@/db.ts';
|
import { DittoDB } from '@/db/DittoDB.ts';
|
||||||
import { type DittoEvent } from '@/interfaces/DittoEvent.ts';
|
import { type DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||||
import { DittoTables } from '@/db/DittoTables.ts';
|
import { DittoTables } from '@/db/DittoTables.ts';
|
||||||
import { Conf } from '@/config.ts';
|
import { Conf } from '@/config.ts';
|
||||||
|
@ -239,7 +239,7 @@ function gatherReportedProfiles({ events, store, signal }: HydrateOpts): Promise
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Collect author stats from the events. */
|
/** Collect author stats from the events. */
|
||||||
function gatherAuthorStats(events: DittoEvent[]): Promise<DittoTables['author_stats'][]> {
|
async function gatherAuthorStats(events: DittoEvent[]): Promise<DittoTables['author_stats'][]> {
|
||||||
const pubkeys = new Set<string>(
|
const pubkeys = new Set<string>(
|
||||||
events
|
events
|
||||||
.filter((event) => event.kind === 0)
|
.filter((event) => event.kind === 0)
|
||||||
|
@ -250,7 +250,8 @@ function gatherAuthorStats(events: DittoEvent[]): Promise<DittoTables['author_st
|
||||||
return Promise.resolve([]);
|
return Promise.resolve([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return db
|
const kysely = await DittoDB.getInstance();
|
||||||
|
return kysely
|
||||||
.selectFrom('author_stats')
|
.selectFrom('author_stats')
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.where('pubkey', 'in', [...pubkeys])
|
.where('pubkey', 'in', [...pubkeys])
|
||||||
|
@ -258,7 +259,7 @@ function gatherAuthorStats(events: DittoEvent[]): Promise<DittoTables['author_st
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Collect event stats from the events. */
|
/** Collect event stats from the events. */
|
||||||
function gatherEventStats(events: DittoEvent[]): Promise<DittoTables['event_stats'][]> {
|
async function gatherEventStats(events: DittoEvent[]): Promise<DittoTables['event_stats'][]> {
|
||||||
const ids = new Set<string>(
|
const ids = new Set<string>(
|
||||||
events
|
events
|
||||||
.filter((event) => event.kind === 1)
|
.filter((event) => event.kind === 1)
|
||||||
|
@ -269,7 +270,8 @@ function gatherEventStats(events: DittoEvent[]): Promise<DittoTables['event_stat
|
||||||
return Promise.resolve([]);
|
return Promise.resolve([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return db
|
const kysely = await DittoDB.getInstance();
|
||||||
|
return kysely
|
||||||
.selectFrom('event_stats')
|
.selectFrom('event_stats')
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.where('event_id', 'in', [...ids])
|
.where('event_id', 'in', [...ids])
|
||||||
|
|
Loading…
Reference in New Issue