mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 03:19:46 +00:00
Merge branch 'fetch-related' into 'main'
Fetch related events by ID through the RelayStore See merge request soapbox-pub/ditto!709
This commit is contained in:
commit
773cee8b92
4 changed files with 64 additions and 5 deletions
|
|
@ -194,7 +194,7 @@ const pgstore = new DittoPgStore({
|
||||||
});
|
});
|
||||||
|
|
||||||
const pool = new DittoPool({ conf, relay: pgstore });
|
const pool = new DittoPool({ conf, relay: pgstore });
|
||||||
const relay = new DittoRelayStore({ db, conf, relay: pgstore });
|
const relay = new DittoRelayStore({ db, conf, pool, relay: pgstore });
|
||||||
|
|
||||||
await seedZapSplits({ conf, relay });
|
await seedZapSplits({ conf, relay });
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,9 +65,29 @@ Deno.test('updateAuthorData sets nip05', async () => {
|
||||||
assertEquals(row?.nip05_hostname, 'gleasonator.dev');
|
assertEquals(row?.nip05_hostname, 'gleasonator.dev');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Deno.test('fetchRelated', async () => {
|
||||||
|
await using test = setupTest();
|
||||||
|
const { pool, store } = test;
|
||||||
|
|
||||||
|
const post = genEvent({ kind: 1, content: 'hi' });
|
||||||
|
const reply = genEvent({ kind: 1, content: 'wussup?', tags: [['e', post.id], ['p', post.pubkey]] });
|
||||||
|
|
||||||
|
await pool.event(post);
|
||||||
|
await pool.event(reply);
|
||||||
|
|
||||||
|
await store.event(reply);
|
||||||
|
|
||||||
|
await waitFor(async () => {
|
||||||
|
const { count } = await test.store.count([{ ids: [post.id] }]);
|
||||||
|
return count > 0;
|
||||||
|
}, 3000);
|
||||||
|
});
|
||||||
|
|
||||||
function setupTest(cb?: (req: Request) => Response | Promise<Response>) {
|
function setupTest(cb?: (req: Request) => Response | Promise<Response>) {
|
||||||
const conf = new DittoConf(Deno.env);
|
const conf = new DittoConf(Deno.env);
|
||||||
const db = new DittoPolyPg(conf.databaseUrl);
|
const db = new DittoPolyPg(conf.databaseUrl);
|
||||||
|
|
||||||
|
const pool = new MockRelay();
|
||||||
const relay = new MockRelay();
|
const relay = new MockRelay();
|
||||||
|
|
||||||
const mockFetch: typeof fetch = async (input, init) => {
|
const mockFetch: typeof fetch = async (input, init) => {
|
||||||
|
|
@ -79,11 +99,12 @@ function setupTest(cb?: (req: Request) => Response | Promise<Response>) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const store = new DittoRelayStore({ conf, db, relay, fetch: mockFetch });
|
const store = new DittoRelayStore({ conf, db, pool, relay, fetch: mockFetch });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
db,
|
db,
|
||||||
conf,
|
conf,
|
||||||
|
pool,
|
||||||
store,
|
store,
|
||||||
[Symbol.asyncDispose]: async () => {
|
[Symbol.asyncDispose]: async () => {
|
||||||
await store[Symbol.asyncDispose]();
|
await store[Symbol.asyncDispose]();
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import { DittoPush } from '@/DittoPush.ts';
|
||||||
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||||
import { RelayError } from '@/RelayError.ts';
|
import { RelayError } from '@/RelayError.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { eventAge, nostrNow, Time } from '@/utils.ts';
|
import { eventAge, isNostrId, nostrNow, Time } from '@/utils.ts';
|
||||||
import { getAmount } from '@/utils/bolt11.ts';
|
import { getAmount } from '@/utils/bolt11.ts';
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from '@/utils/log.ts';
|
||||||
import { purifyEvent } from '@/utils/purify.ts';
|
import { purifyEvent } from '@/utils/purify.ts';
|
||||||
|
|
@ -46,6 +46,7 @@ import { nip19 } from 'nostr-tools';
|
||||||
interface DittoRelayStoreOpts {
|
interface DittoRelayStoreOpts {
|
||||||
db: DittoDB;
|
db: DittoDB;
|
||||||
conf: DittoConf;
|
conf: DittoConf;
|
||||||
|
pool: NRelay;
|
||||||
relay: NRelay;
|
relay: NRelay;
|
||||||
fetch?: typeof fetch;
|
fetch?: typeof fetch;
|
||||||
}
|
}
|
||||||
|
|
@ -192,7 +193,12 @@ export class DittoRelayStore implements NRelay {
|
||||||
this.prewarmLinkPreview(event, signal),
|
this.prewarmLinkPreview(event, signal),
|
||||||
this.generateSetEvents(event),
|
this.generateSetEvents(event),
|
||||||
])
|
])
|
||||||
.then(() => this.webPush(event))
|
.then(() =>
|
||||||
|
Promise.allSettled([
|
||||||
|
this.webPush(event),
|
||||||
|
this.fetchRelated(event),
|
||||||
|
])
|
||||||
|
)
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -323,6 +329,37 @@ export class DittoRelayStore implements NRelay {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async fetchRelated(event: NostrEvent): Promise<void> {
|
||||||
|
const ids = new Set<string>();
|
||||||
|
|
||||||
|
for (const tag of event.tags) {
|
||||||
|
const [name, value] = tag;
|
||||||
|
|
||||||
|
if ((name === 'e' || name === 'q') && isNostrId(value) && !this.encounters.has(value)) {
|
||||||
|
ids.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { db, pool } = this.opts;
|
||||||
|
|
||||||
|
if (ids.size) {
|
||||||
|
const query = db.kysely
|
||||||
|
.selectFrom('nostr_events')
|
||||||
|
.select('id')
|
||||||
|
.where('id', 'in', [...ids]);
|
||||||
|
|
||||||
|
for (const row of await query.execute().catch(() => [])) {
|
||||||
|
ids.delete(row.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ids.size) {
|
||||||
|
for (const event of await pool.query([{ ids: [...ids] }])) {
|
||||||
|
await this.event(event).catch(() => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async prewarmLinkPreview(event: NostrEvent, signal?: AbortSignal): Promise<void> {
|
private async prewarmLinkPreview(event: NostrEvent, signal?: AbortSignal): Promise<void> {
|
||||||
const { firstUrl } = parseNoteContent(stripimeta(event.content, event.tags), [], this.opts);
|
const { firstUrl } = parseNoteContent(stripimeta(event.content, event.tags), [], this.opts);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Semaphore } from '@core/asyncutil';
|
import { Semaphore } from '@core/asyncutil';
|
||||||
import { NostrEvent } from '@nostrify/nostrify';
|
import { NostrEvent } from '@nostrify/nostrify';
|
||||||
|
import { MockRelay } from '@nostrify/nostrify/test';
|
||||||
|
|
||||||
import { DittoConf } from '@ditto/conf';
|
import { DittoConf } from '@ditto/conf';
|
||||||
import { DittoPolyPg } from '@ditto/db';
|
import { DittoPolyPg } from '@ditto/db';
|
||||||
|
|
@ -11,7 +12,7 @@ const conf = new DittoConf(Deno.env);
|
||||||
const db = new DittoPolyPg(conf.databaseUrl);
|
const db = new DittoPolyPg(conf.databaseUrl);
|
||||||
|
|
||||||
const pgstore = new DittoPgStore({ db, conf });
|
const pgstore = new DittoPgStore({ db, conf });
|
||||||
const relaystore = new DittoRelayStore({ conf, db, relay: pgstore });
|
const relaystore = new DittoRelayStore({ conf, db, pool: new MockRelay(), relay: pgstore });
|
||||||
|
|
||||||
const sem = new Semaphore(5);
|
const sem = new Semaphore(5);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue