feat: profile cache worker relay
This commit is contained in:
parent
084558b3e7
commit
6eef8c7fef
104
packages/app/src/Cache/ProfileWorkeCache.ts
Normal file
104
packages/app/src/Cache/ProfileWorkeCache.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import { CachedTable, CacheEvents, removeUndefined } from "@snort/shared";
|
||||
import { CachedMetadata, mapEventToProfile, NostrEvent } from "@snort/system";
|
||||
import { WorkerRelayInterface } from "@snort/worker-relay";
|
||||
import EventEmitter from "eventemitter3";
|
||||
|
||||
export class ProfileCacheRelayWorker extends EventEmitter<CacheEvents> implements CachedTable<CachedMetadata> {
|
||||
#relay: WorkerRelayInterface;
|
||||
#keys = new Set<string>();
|
||||
#cache = new Map<string, CachedMetadata>();
|
||||
|
||||
constructor(relay: WorkerRelayInterface) {
|
||||
super();
|
||||
this.#relay = relay;
|
||||
}
|
||||
|
||||
async preload() {
|
||||
const ids = await this.#relay.sql("select distinct(pubkey) from events where kind = ?", [0]);
|
||||
this.#keys = new Set<string>(ids.map(a => a[0] as string));
|
||||
}
|
||||
|
||||
keysOnTable(): string[] {
|
||||
return [...this.#keys];
|
||||
}
|
||||
|
||||
getFromCache(key?: string | undefined) {
|
||||
if (key) {
|
||||
return this.#cache.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
discover(ev: NostrEvent) {
|
||||
if (ev.kind === 0) {
|
||||
this.#keys.add(ev.pubkey);
|
||||
}
|
||||
}
|
||||
|
||||
async get(key?: string | undefined) {
|
||||
if (key) {
|
||||
const cached = this.getFromCache(key);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
const res = await this.bulkGet([key]);
|
||||
if (res.length > 0) {
|
||||
return res[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async bulkGet(keys: string[]) {
|
||||
if (keys.length === 0) return [];
|
||||
|
||||
const results = await this.#relay.req({
|
||||
id: "ProfileCacheRelayWorker.bulkGet",
|
||||
filters: [
|
||||
{
|
||||
authors: keys,
|
||||
kinds: [0],
|
||||
},
|
||||
],
|
||||
});
|
||||
const mapped = removeUndefined(results.result.map(a => mapEventToProfile(a)));
|
||||
for (const pf of mapped) {
|
||||
this.#cache.set(this.key(pf), pf);
|
||||
}
|
||||
this.emit(
|
||||
"change",
|
||||
mapped.map(a => this.key(a)),
|
||||
);
|
||||
console.debug("ProfileCacheRelayWorker", keys, results);
|
||||
return mapped;
|
||||
}
|
||||
|
||||
async set(obj: CachedMetadata) {
|
||||
this.#keys.add(this.key(obj));
|
||||
}
|
||||
|
||||
async bulkSet(obj: CachedMetadata[] | readonly CachedMetadata[]) {
|
||||
const mapped = obj.map(a => this.key(a));
|
||||
mapped.forEach(a => this.#keys.add(a));
|
||||
this.emit("change", mapped);
|
||||
}
|
||||
|
||||
async update<TWithCreated extends CachedMetadata & { created: number; loaded: number }>(
|
||||
m: TWithCreated,
|
||||
): Promise<"new" | "refresh" | "updated" | "no_change"> {
|
||||
// do nothing
|
||||
return "refresh";
|
||||
}
|
||||
|
||||
async buffer(keys: string[]) {
|
||||
const missing = keys.filter(a => !this.#cache.has(a));
|
||||
const res = await this.bulkGet(missing);
|
||||
return missing.filter(a => !res.some(b => this.key(b) === a));
|
||||
}
|
||||
|
||||
key(of: CachedMetadata) {
|
||||
return of.pubkey;
|
||||
}
|
||||
|
||||
snapshot() {
|
||||
return [...this.#cache.values()];
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { RelayMetricCache, UserProfileCache, UserRelaysCache } from "@snort/system";
|
||||
import { RelayMetricCache, UserRelaysCache } from "@snort/system";
|
||||
import { SnortSystemDb } from "@snort/system-web";
|
||||
import { WorkerRelayInterface } from "@snort/worker-relay";
|
||||
import WorkerRelayPath from "@snort/worker-relay/dist/worker?worker&url";
|
||||
@ -6,6 +6,7 @@ import WorkerRelayPath from "@snort/worker-relay/dist/worker?worker&url";
|
||||
import { ChatCache } from "./ChatCache";
|
||||
import { EventCacheWorker } from "./EventCacheWorker";
|
||||
import { GiftWrapCache } from "./GiftWrapCache";
|
||||
import { ProfileCacheRelayWorker } from "./ProfileWorkeCache";
|
||||
|
||||
export const Relay = new WorkerRelayInterface(WorkerRelayPath);
|
||||
export async function initRelayWorker() {
|
||||
@ -21,9 +22,10 @@ export async function initRelayWorker() {
|
||||
}
|
||||
|
||||
export const SystemDb = new SnortSystemDb();
|
||||
export const UserCache = new UserProfileCache(SystemDb.users);
|
||||
export const UserRelays = new UserRelaysCache(SystemDb.userRelays);
|
||||
export const RelayMetrics = new RelayMetricCache(SystemDb.relayMetrics);
|
||||
|
||||
export const UserCache = new ProfileCacheRelayWorker(Relay);
|
||||
export const EventsCache = new EventCacheWorker(Relay);
|
||||
|
||||
export const Chats = new ChatCache();
|
||||
@ -31,7 +33,7 @@ export const GiftsCache = new GiftWrapCache();
|
||||
|
||||
export async function preload(follows?: Array<string>) {
|
||||
const preloads = [
|
||||
UserCache.preload(follows),
|
||||
UserCache.preload(),
|
||||
Chats.preload(),
|
||||
RelayMetrics.preload(),
|
||||
GiftsCache.preload(),
|
||||
|
@ -2,7 +2,7 @@ import { FeedCache } from "@snort/shared";
|
||||
import { ReactNode, useEffect, useState, useSyncExternalStore } from "react";
|
||||
import { FormattedMessage, FormattedNumber } from "react-intl";
|
||||
|
||||
import { Chats, GiftsCache, Relay, RelayMetrics, UserCache } from "@/Cache";
|
||||
import { Chats, GiftsCache, Relay, RelayMetrics } from "@/Cache";
|
||||
import AsyncButton from "@/Components/Button/AsyncButton";
|
||||
|
||||
export function CacheSettings() {
|
||||
@ -12,7 +12,6 @@ export function CacheSettings() {
|
||||
<FormattedMessage defaultMessage="Cache" id="DBiVK1" />
|
||||
</h3>
|
||||
<RelayCacheStats />
|
||||
<CacheDetails cache={UserCache} name={<FormattedMessage defaultMessage="Profiles" id="2zJXeA" />} />
|
||||
<CacheDetails cache={Chats} name={<FormattedMessage defaultMessage="Chats" id="ABAQyo" />} />
|
||||
<CacheDetails cache={RelayMetrics} name={<FormattedMessage defaultMessage="Relay Metrics" id="tjpYlr" />} />
|
||||
<CacheDetails cache={GiftsCache} name={<FormattedMessage defaultMessage="Gift Wraps" id="fjAcWo" />} />
|
||||
|
@ -28,6 +28,7 @@ System.on("auth", async (c, r, cb) => {
|
||||
System.on("event", (_, ev) => {
|
||||
Relay.event(ev);
|
||||
EventsCache.discover(ev);
|
||||
UserCache.discover(ev);
|
||||
});
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user