db/events: refactor insertEvent into smaller functions
This commit is contained in:
parent
96ff31719e
commit
f8b2efb484
|
@ -1,5 +1,5 @@
|
||||||
import { db, type TagRow } from '@/db.ts';
|
import { db } from '@/db.ts';
|
||||||
import { type Event, type Insertable, SqliteError } from '@/deps.ts';
|
import { type Event, SqliteError } from '@/deps.ts';
|
||||||
import { isParameterizedReplaceableKind } from '@/kinds.ts';
|
import { isParameterizedReplaceableKind } from '@/kinds.ts';
|
||||||
import { jsonMetaContentSchema } from '@/schemas/nostr.ts';
|
import { jsonMetaContentSchema } from '@/schemas/nostr.ts';
|
||||||
import { EventData } from '@/types.ts';
|
import { EventData } from '@/types.ts';
|
||||||
|
@ -7,6 +7,7 @@ import { isNostrId, isURL } from '@/utils.ts';
|
||||||
|
|
||||||
import type { DittoFilter, GetFiltersOpts } from '@/filter.ts';
|
import type { DittoFilter, GetFiltersOpts } from '@/filter.ts';
|
||||||
|
|
||||||
|
/** Function to decide whether or not to index a tag. */
|
||||||
type TagCondition = ({ event, count, value }: {
|
type TagCondition = ({ event, count, value }: {
|
||||||
event: Event;
|
event: Event;
|
||||||
data: EventData;
|
data: EventData;
|
||||||
|
@ -28,47 +29,39 @@ const tagConditions: Record<string, TagCondition> = {
|
||||||
/** Insert an event (and its tags) into the database. */
|
/** Insert an event (and its tags) into the database. */
|
||||||
function insertEvent(event: Event, data: EventData): Promise<void> {
|
function insertEvent(event: Event, data: EventData): Promise<void> {
|
||||||
return db.transaction().execute(async (trx) => {
|
return db.transaction().execute(async (trx) => {
|
||||||
|
/** Insert the event into the database. */
|
||||||
|
async function addEvent() {
|
||||||
await trx.insertInto('events')
|
await trx.insertInto('events')
|
||||||
.values({
|
.values({ ...event, tags: JSON.stringify(event.tags) })
|
||||||
...event,
|
|
||||||
tags: JSON.stringify(event.tags),
|
|
||||||
})
|
|
||||||
.execute();
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add search data to the FTS table. */
|
||||||
|
async function indexSearch() {
|
||||||
const searchContent = buildSearchContent(event);
|
const searchContent = buildSearchContent(event);
|
||||||
if (searchContent) {
|
if (!searchContent) return;
|
||||||
await trx.insertInto('events_fts')
|
await trx.insertInto('events_fts')
|
||||||
.values({ id: event.id, content: searchContent.substring(0, 1000) })
|
.values({ id: event.id, content: searchContent.substring(0, 1000) })
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
const tagCounts: Record<string, number> = {};
|
/** Index event tags depending on the conditions defined above. */
|
||||||
const tags = event.tags.reduce<Insertable<TagRow>[]>((results, [name, value]) => {
|
async function indexTags() {
|
||||||
tagCounts[name] = (tagCounts[name] || 0) + 1;
|
const tags = filterIndexableTags(event, data);
|
||||||
|
const rows = tags.map(([tag, value]) => ({ event_id: event.id, tag, value }));
|
||||||
|
|
||||||
const shouldIndex = tagConditions[name]?.({
|
if (!tags.length) return;
|
||||||
event,
|
|
||||||
data,
|
|
||||||
count: tagCounts[name] - 1,
|
|
||||||
value,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (value && value.length < 200 && shouldIndex) {
|
|
||||||
results.push({
|
|
||||||
event_id: event.id,
|
|
||||||
tag: name,
|
|
||||||
value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (tags.length) {
|
|
||||||
await trx.insertInto('tags')
|
await trx.insertInto('tags')
|
||||||
.values(tags)
|
.values(rows)
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run the queries.
|
||||||
|
await Promise.all([
|
||||||
|
addEvent(),
|
||||||
|
indexTags(),
|
||||||
|
indexSearch(),
|
||||||
|
]);
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
// Don't throw for duplicate events.
|
// Don't throw for duplicate events.
|
||||||
if (error instanceof SqliteError && error.code === 19) {
|
if (error instanceof SqliteError && error.code === 19) {
|
||||||
|
@ -197,6 +190,29 @@ async function countFilters<K extends number>(filters: DittoFilter<K>[]): Promis
|
||||||
return Number(count);
|
return Number(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Return only the tags that should be indexed. */
|
||||||
|
function filterIndexableTags(event: Event, data: EventData): string[][] {
|
||||||
|
const tagCounts: Record<string, number> = {};
|
||||||
|
|
||||||
|
return event.tags.reduce<string[][]>((results, tag) => {
|
||||||
|
const [name, value] = tag;
|
||||||
|
tagCounts[name] = (tagCounts[name] || 0) + 1;
|
||||||
|
|
||||||
|
const shouldIndex = tagConditions[name]?.({
|
||||||
|
event,
|
||||||
|
data,
|
||||||
|
count: tagCounts[name] - 1,
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (value && value.length < 200 && shouldIndex) {
|
||||||
|
results.push(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
/** Build a search index from the event. */
|
/** Build a search index from the event. */
|
||||||
function buildSearchContent(event: Event): string {
|
function buildSearchContent(event: Event): string {
|
||||||
switch (event.kind) {
|
switch (event.kind) {
|
||||||
|
|
Loading…
Reference in New Issue