mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 03:19:46 +00:00
Make DittoAPIStore and DittoRelay separate things
This commit is contained in:
parent
52a9017730
commit
cce78f2b0c
3 changed files with 66 additions and 36 deletions
|
|
@ -1,4 +1,54 @@
|
|||
import { DittoRelayStore } from '@/storages/DittoRelayStore.ts';
|
||||
import { DittoConf } from '@ditto/conf';
|
||||
import { DittoDB } from '@ditto/db';
|
||||
import { logi } from '@soapbox/logi';
|
||||
import { NostrEvent, NRelay } from '@nostrify/nostrify';
|
||||
|
||||
export class DittoAPIStore extends DittoRelayStore {
|
||||
import { DittoRelayStore } from '@/storages/DittoRelayStore.ts';
|
||||
import { errorJson } from '@/utils/log.ts';
|
||||
import { purifyEvent } from '@/utils/purify.ts';
|
||||
|
||||
interface DittoAPIStoreOpts {
|
||||
db: DittoDB;
|
||||
conf: DittoConf;
|
||||
pool: NRelay;
|
||||
relay: NRelay;
|
||||
fetch?: typeof fetch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store used by Ditto's Mastodon API implementation.
|
||||
* It extends the RelayStore to publish events to the wider Nostr network.
|
||||
*/
|
||||
export class DittoAPIStore extends DittoRelayStore {
|
||||
_opts: DittoAPIStoreOpts;
|
||||
|
||||
private _ns = 'ditto.relay.store';
|
||||
|
||||
constructor(opts: DittoAPIStoreOpts) {
|
||||
super(opts);
|
||||
this._opts = opts;
|
||||
}
|
||||
|
||||
override async event(event: NostrEvent, opts?: { signal?: AbortSignal }): Promise<void> {
|
||||
const { pool } = this._opts;
|
||||
const { id, kind } = event;
|
||||
|
||||
await super.event(event, opts);
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
// `purifyEvent` is important, or you will suffer.
|
||||
await pool.event(purifyEvent(event), opts);
|
||||
} catch (e) {
|
||||
logi({ level: 'error', ns: this._ns, source: 'publish', id, kind, error: errorJson(e) });
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
override async close(): Promise<void> {
|
||||
const { pool } = this._opts;
|
||||
|
||||
await pool.close();
|
||||
await super.close();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@ Deno.test('updateAuthorData sets nip05', async () => {
|
|||
function setupTest(cb: (req: Request) => Response | Promise<Response>) {
|
||||
const conf = new DittoConf(Deno.env);
|
||||
const db = new DittoPolyPg(conf.databaseUrl);
|
||||
|
||||
const pool = new MockRelay();
|
||||
const relay = new MockRelay();
|
||||
|
||||
const mockFetch: typeof fetch = async (input, init) => {
|
||||
|
|
@ -50,7 +48,7 @@ function setupTest(cb: (req: Request) => Response | Promise<Response>) {
|
|||
return await cb(req);
|
||||
};
|
||||
|
||||
const store = new DittoRelayStore({ conf, db, relay, pool, fetch: mockFetch });
|
||||
const store = new DittoRelayStore({ conf, db, relay, fetch: mockFetch });
|
||||
|
||||
return {
|
||||
db,
|
||||
|
|
|
|||
|
|
@ -46,11 +46,11 @@ import { nip19 } from 'nostr-tools';
|
|||
interface DittoRelayStoreOpts {
|
||||
db: DittoDB;
|
||||
conf: DittoConf;
|
||||
pool: NRelay;
|
||||
relay: NRelay;
|
||||
fetch?: typeof fetch;
|
||||
}
|
||||
|
||||
/** Backing storage class for Ditto relay implementation at `/relay`. */
|
||||
export class DittoRelayStore implements NRelay {
|
||||
private push: DittoPush;
|
||||
private encounters = new LRUCache<string, true>({ max: 5000 });
|
||||
|
|
@ -60,7 +60,7 @@ export class DittoRelayStore implements NRelay {
|
|||
private faviconCache: SimpleLRU<string, URL>;
|
||||
private nip05Cache: SimpleLRU<string, nip19.ProfilePointer>;
|
||||
|
||||
private ns = 'ditto.apistore';
|
||||
private ns = 'ditto.api.store';
|
||||
|
||||
constructor(private opts: DittoRelayStoreOpts) {
|
||||
const { conf, db } = this.opts;
|
||||
|
|
@ -95,31 +95,6 @@ export class DittoRelayStore implements NRelay {
|
|||
);
|
||||
}
|
||||
|
||||
req(
|
||||
filters: NostrFilter[],
|
||||
opts?: { signal?: AbortSignal },
|
||||
): AsyncIterable<NostrRelayEVENT | NostrRelayEOSE | NostrRelayCLOSED> {
|
||||
const { relay } = this.opts;
|
||||
return relay.req(filters, opts);
|
||||
}
|
||||
|
||||
async event(event: NostrEvent, opts?: { publish?: boolean; signal?: AbortSignal }): Promise<void> {
|
||||
const { pool } = this.opts;
|
||||
const { id, kind } = event;
|
||||
|
||||
await this.handleEvent(event, opts);
|
||||
|
||||
if (opts?.publish) {
|
||||
(async () => {
|
||||
try {
|
||||
await pool.event(purifyEvent(event), opts);
|
||||
} catch (e) {
|
||||
logi({ level: 'error', ns: this.ns, source: 'publish', id, kind, error: errorJson(e) });
|
||||
}
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
/** Open a firehose to the relay. */
|
||||
private async listen(): Promise<void> {
|
||||
const { relay } = this.opts;
|
||||
|
|
@ -128,16 +103,24 @@ export class DittoRelayStore implements NRelay {
|
|||
for await (const msg of relay.req([{ limit: 0 }], { signal })) {
|
||||
if (msg[0] === 'EVENT') {
|
||||
const [, , event] = msg;
|
||||
await this.handleEvent(event, { signal });
|
||||
await this.event(event, { signal });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
req(
|
||||
filters: NostrFilter[],
|
||||
opts?: { signal?: AbortSignal },
|
||||
): AsyncIterable<NostrRelayEVENT | NostrRelayEOSE | NostrRelayCLOSED> {
|
||||
const { relay } = this.opts;
|
||||
return relay.req(filters, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Common pipeline function to process (and maybe store) events.
|
||||
* It is idempotent, so it can be called multiple times for the same event.
|
||||
*/
|
||||
private async handleEvent(event: DittoEvent, opts: { signal?: AbortSignal } = {}): Promise<void> {
|
||||
async event(event: DittoEvent, opts: { publish?: boolean; signal?: AbortSignal } = {}): Promise<void> {
|
||||
const { conf, relay } = this.opts;
|
||||
const { signal } = opts;
|
||||
|
||||
|
|
@ -474,11 +457,10 @@ export class DittoRelayStore implements NRelay {
|
|||
}
|
||||
|
||||
async close(): Promise<void> {
|
||||
const { relay, pool } = this.opts;
|
||||
const { relay } = this.opts;
|
||||
|
||||
this.controller.abort();
|
||||
|
||||
await pool.close();
|
||||
await relay.close();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue