stats: update note count

This commit is contained in:
Alex Gleason 2023-12-10 11:10:11 -06:00
parent 2ab7616795
commit bababe56f3
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
3 changed files with 54 additions and 19 deletions

View File

@ -13,6 +13,22 @@ interface DittoDB {
users: UserRow; users: UserRow;
relays: RelayRow; relays: RelayRow;
unattached_media: UnattachedMediaRow; unattached_media: UnattachedMediaRow;
pubkey_stats: PubkeyStatsRow;
event_stats: EventStatsRow;
}
interface PubkeyStatsRow {
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 { interface EventRow {
@ -101,7 +117,7 @@ async function migrate() {
console.log('Everything up-to-date.'); console.log('Everything up-to-date.');
} else { } else {
console.log('Migrations finished!'); console.log('Migrations finished!');
for (const { migrationName, status } of results.results) { for (const { migrationName, status } of results.results!) {
console.log(` - ${migrationName}: ${status}`); console.log(` - ${migrationName}: ${status}`);
} }
} }
@ -110,4 +126,4 @@ async function migrate() {
await migrate(); await migrate();
export { db, type DittoDB, type EventRow, type TagRow, type UserRow }; export { db, type DittoDB, type EventRow, type EventStatsRow, type PubkeyStatsRow, type TagRow, type UserRow };

View File

@ -8,6 +8,7 @@ import { isEphemeralKind } from '@/kinds.ts';
import * as mixer from '@/mixer.ts'; import * as mixer from '@/mixer.ts';
import { publish } from '@/pool.ts'; import { publish } from '@/pool.ts';
import { isLocallyFollowed } from '@/queries.ts'; import { isLocallyFollowed } from '@/queries.ts';
import { updateStats } from '@/stats.ts';
import { Sub } from '@/subs.ts'; import { Sub } from '@/subs.ts';
import { getTagSet } from '@/tags.ts'; import { getTagSet } from '@/tags.ts';
import { eventAge, isRelay, nostrDate, Time } from '@/utils.ts'; import { eventAge, isRelay, nostrDate, Time } from '@/utils.ts';
@ -68,7 +69,10 @@ async function storeEvent(event: Event, data: EventData): Promise<void> {
if (deletion) { if (deletion) {
return Promise.reject(new RelayError('blocked', 'event was deleted')); return Promise.reject(new RelayError('blocked', 'event was deleted'));
} else { } else {
await eventsDB.insertEvent(event, data).catch(console.warn); await Promise.all([
eventsDB.insertEvent(event, data).catch(console.warn),
updateStats(event),
]);
} }
} else { } else {
return Promise.reject(new RelayError('blocked', 'only registered users can post')); return Promise.reject(new RelayError('blocked', 'only registered users can post'));

View File

@ -1,11 +1,17 @@
import { open as lmdb } from 'npm:lmdb'; import { db, type PubkeyStatsRow } from '@/db.ts';
import { Event } from '@/deps.ts'; import { Event } from '@/deps.ts';
const db = lmdb({ path: 'data/ditto.lmdb' }); type PubkeyStat = keyof Omit<PubkeyStatsRow, 'pubkey'>;
/** Store stats for the event in LMDB. */ /** Store stats for the event in LMDB. */
async function saveStats(event: Event): Promise<void> { function updateStats(event: Event) {
return updateStatsQuery(event).execute();
}
async function updateStatsQuery(event: Event) {
switch (event.kind) { switch (event.kind) {
case 1:
return incrementPubkeyStatQuery(event.pubkey, 'notes_count', 1);
case 6: case 6:
return await incrementMentionedEvent(event, 'reposts'); return await incrementMentionedEvent(event, 'reposts');
case 7: case 7:
@ -13,20 +19,29 @@ async function saveStats(event: Event): Promise<void> {
} }
} }
/** Increment the subkey for the first mentioned event. */ function incrementPubkeyStatQuery(pubkey: string, stat: PubkeyStat, diff: number) {
async function incrementMentionedEvent(event: Event, subkey: string): Promise<void> { const row: PubkeyStatsRow = {
const eventId = event.tags.find(([name]) => name === 'e')?.[1]; pubkey,
if (eventId) { followers_count: 0,
return await incrementKey([eventId, subkey]); following_count: 0,
} notes_count: 0,
};
row[stat] = diff;
return db.insertInto('pubkey_stats')
.values(row)
.onConflict((oc) =>
oc
.column('pubkey')
.doUpdateSet((eb) => ({
[stat]: eb(stat, '+', diff),
}))
);
} }
/** Increase the counter by 1, or set the key if it doesn't exist. */ function findFirstTag({ tags }: Event, name: string): string | undefined {
function incrementKey(key: string[]): Promise<void> { return tags.find(([n]) => n === name)?.[1];
return db.transaction(() => {
const value = db.get(key) || 0;
db.put(key, value + 1);
});
} }
export { saveStats }; export { updateStats };