Setup relay metrics
This commit is contained in:
@ -1,9 +1,10 @@
|
|||||||
import { UserProfileCache, UserRelaysCache } from "@snort/system";
|
import { UserProfileCache, UserRelaysCache, RelayMetricCache } from "@snort/system";
|
||||||
import { DmCache } from "./DMCache";
|
import { DmCache } from "./DMCache";
|
||||||
import { InteractionCache } from "./EventInteractionCache";
|
import { InteractionCache } from "./EventInteractionCache";
|
||||||
|
|
||||||
export const UserCache = new UserProfileCache();
|
export const UserCache = new UserProfileCache();
|
||||||
export const UserRelays = new UserRelaysCache();
|
export const UserRelays = new UserRelaysCache();
|
||||||
|
export const RelayMetrics = new RelayMetricCache();
|
||||||
export { DmCache };
|
export { DmCache };
|
||||||
|
|
||||||
export async function preload(follows?: Array<string>) {
|
export async function preload(follows?: Array<string>) {
|
||||||
@ -12,6 +13,7 @@ export async function preload(follows?: Array<string>) {
|
|||||||
DmCache.preload(),
|
DmCache.preload(),
|
||||||
InteractionCache.preload(),
|
InteractionCache.preload(),
|
||||||
UserRelays.preload(follows),
|
UserRelays.preload(follows),
|
||||||
|
RelayMetrics.preload(),
|
||||||
];
|
];
|
||||||
await Promise.all(preloads);
|
await Promise.all(preloads);
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import { StrictMode } from "react";
|
|||||||
import * as ReactDOM from "react-dom/client";
|
import * as ReactDOM from "react-dom/client";
|
||||||
import { Provider } from "react-redux";
|
import { Provider } from "react-redux";
|
||||||
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
||||||
|
import { EventPublisher, NostrSystem, ProfileLoaderService } from "@snort/system";
|
||||||
|
|
||||||
import * as serviceWorkerRegistration from "serviceWorkerRegistration";
|
import * as serviceWorkerRegistration from "serviceWorkerRegistration";
|
||||||
import { IntlProvider } from "IntlProvider";
|
import { IntlProvider } from "IntlProvider";
|
||||||
@ -33,16 +34,16 @@ import { SubscribeRoutes } from "Pages/subscribe";
|
|||||||
import ZapPoolPage from "Pages/ZapPool";
|
import ZapPoolPage from "Pages/ZapPool";
|
||||||
import DebugPage from "Pages/Debug";
|
import DebugPage from "Pages/Debug";
|
||||||
import { db } from "Db";
|
import { db } from "Db";
|
||||||
import { preload, UserCache } from "Cache";
|
import { preload, RelayMetrics, UserCache, UserRelays } from "Cache";
|
||||||
import { LoginStore } from "Login";
|
import { LoginStore } from "Login";
|
||||||
import { EventPublisher, NostrSystem, ProfileLoaderService } from "@snort/system";
|
|
||||||
import { UserRelays } from "Cache";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Singleton nostr system
|
* Singleton nostr system
|
||||||
*/
|
*/
|
||||||
export const System = new NostrSystem({
|
export const System = new NostrSystem({
|
||||||
relayCache: UserRelays,
|
relayCache: UserRelays,
|
||||||
|
profileCache: UserCache,
|
||||||
|
relayMetrics: RelayMetrics,
|
||||||
authHandler: async (c, r) => {
|
authHandler: async (c, r) => {
|
||||||
const { publicKey, privateKey } = LoginStore.snapshot();
|
const { publicKey, privateKey } = LoginStore.snapshot();
|
||||||
if (publicKey) {
|
if (publicKey) {
|
||||||
|
@ -64,7 +64,7 @@ export class Connection extends ExternalStore<ConnectionStateSnapshot> {
|
|||||||
OnConnected?: () => void;
|
OnConnected?: () => void;
|
||||||
OnEvent?: (sub: string, e: TaggedRawEvent) => void;
|
OnEvent?: (sub: string, e: TaggedRawEvent) => void;
|
||||||
OnEose?: (sub: string) => void;
|
OnEose?: (sub: string) => void;
|
||||||
OnDisconnect?: (id: string) => void;
|
OnDisconnect?: (code: number) => void;
|
||||||
Auth?: AuthHandler;
|
Auth?: AuthHandler;
|
||||||
AwaitingAuth: Map<string, boolean>;
|
AwaitingAuth: Map<string, boolean>;
|
||||||
Authed = false;
|
Authed = false;
|
||||||
@ -162,7 +162,7 @@ export class Connection extends ExternalStore<ConnectionStateSnapshot> {
|
|||||||
this.ReconnectTimer = undefined;
|
this.ReconnectTimer = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.OnDisconnect?.(this.Id);
|
this.OnDisconnect?.(e.code);
|
||||||
this.#resetQueues();
|
this.#resetQueues();
|
||||||
// reset connection Id on disconnect, for query-tracking
|
// reset connection Id on disconnect, for query-tracking
|
||||||
this.Id = uuid();
|
this.Id = uuid();
|
||||||
|
@ -7,7 +7,17 @@ import { Query } from "./Query";
|
|||||||
import { RelayCache } from "./GossipModel";
|
import { RelayCache } from "./GossipModel";
|
||||||
import { NoteStore } from "./NoteCollection";
|
import { NoteStore } from "./NoteCollection";
|
||||||
import { BuiltRawReqFilter, RequestBuilder } from "./RequestBuilder";
|
import { BuiltRawReqFilter, RequestBuilder } from "./RequestBuilder";
|
||||||
import { MetadataCache, ProfileLoaderService, SystemInterface, SystemSnapshot, UserProfileCache, UserRelaysCache } from ".";
|
import { RelayMetricHandler } from "./RelayMetricHandler";
|
||||||
|
import {
|
||||||
|
MetadataCache,
|
||||||
|
ProfileLoaderService,
|
||||||
|
RelayMetrics,
|
||||||
|
SystemInterface,
|
||||||
|
SystemSnapshot,
|
||||||
|
UserProfileCache,
|
||||||
|
UserRelaysCache,
|
||||||
|
RelayMetricCache
|
||||||
|
} from ".";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages nostr content retrieval system
|
* Manages nostr content retrieval system
|
||||||
@ -40,21 +50,35 @@ export class NostrSystem extends ExternalStore<SystemSnapshot> implements System
|
|||||||
*/
|
*/
|
||||||
#profileCache: FeedCache<MetadataCache>;
|
#profileCache: FeedCache<MetadataCache>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Storage class for relay metrics (connects/disconnects)
|
||||||
|
*/
|
||||||
|
#relayMetricsCache: FeedCache<RelayMetrics>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Profile loading service
|
* Profile loading service
|
||||||
*/
|
*/
|
||||||
#profileLoader: ProfileLoaderService;
|
#profileLoader: ProfileLoaderService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relay metrics handler cache
|
||||||
|
*/
|
||||||
|
#relayMetrics: RelayMetricHandler;
|
||||||
|
|
||||||
constructor(props: {
|
constructor(props: {
|
||||||
authHandler?: AuthHandler,
|
authHandler?: AuthHandler,
|
||||||
relayCache?: RelayCache,
|
relayCache?: RelayCache,
|
||||||
profileCache?: FeedCache<MetadataCache>
|
profileCache?: FeedCache<MetadataCache>
|
||||||
|
relayMetrics?: FeedCache<RelayMetrics>
|
||||||
}) {
|
}) {
|
||||||
super();
|
super();
|
||||||
this.#handleAuth = props.authHandler;
|
this.#handleAuth = props.authHandler;
|
||||||
this.#relayCache = props.relayCache ?? new UserRelaysCache();
|
this.#relayCache = props.relayCache ?? new UserRelaysCache();
|
||||||
this.#profileCache = props.profileCache ?? new UserProfileCache();
|
this.#profileCache = props.profileCache ?? new UserProfileCache();
|
||||||
|
this.#relayMetricsCache = props.relayMetrics ?? new RelayMetricCache();
|
||||||
|
|
||||||
this.#profileLoader = new ProfileLoaderService(this, this.#profileCache);
|
this.#profileLoader = new ProfileLoaderService(this, this.#profileCache);
|
||||||
|
this.#relayMetrics = new RelayMetricHandler(this.#relayMetricsCache);
|
||||||
this.#cleanup();
|
this.#cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +104,7 @@ export class NostrSystem extends ExternalStore<SystemSnapshot> implements System
|
|||||||
this.#sockets.set(addr, c);
|
this.#sockets.set(addr, c);
|
||||||
c.OnEvent = (s, e) => this.OnEvent(s, e);
|
c.OnEvent = (s, e) => this.OnEvent(s, e);
|
||||||
c.OnEose = s => this.OnEndOfStoredEvents(c, s);
|
c.OnEose = s => this.OnEndOfStoredEvents(c, s);
|
||||||
c.OnDisconnect = id => this.OnRelayDisconnect(id);
|
c.OnDisconnect = (code) => this.OnRelayDisconnect(c, code);
|
||||||
await c.Connect();
|
await c.Connect();
|
||||||
} else {
|
} else {
|
||||||
// update settings if already connected
|
// update settings if already connected
|
||||||
@ -91,9 +115,10 @@ export class NostrSystem extends ExternalStore<SystemSnapshot> implements System
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OnRelayDisconnect(id: string) {
|
OnRelayDisconnect(c: Connection, code: number) {
|
||||||
|
this.#relayMetrics.onDisconnect(c, code);
|
||||||
for (const [, q] of this.Queries) {
|
for (const [, q] of this.Queries) {
|
||||||
q.connectionLost(id);
|
q.connectionLost(c.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +146,7 @@ export class NostrSystem extends ExternalStore<SystemSnapshot> implements System
|
|||||||
this.#sockets.set(addr, c);
|
this.#sockets.set(addr, c);
|
||||||
c.OnEvent = (s, e) => this.OnEvent(s, e);
|
c.OnEvent = (s, e) => this.OnEvent(s, e);
|
||||||
c.OnEose = s => this.OnEndOfStoredEvents(c, s);
|
c.OnEose = s => this.OnEndOfStoredEvents(c, s);
|
||||||
c.OnDisconnect = id => this.OnRelayDisconnect(id);
|
c.OnDisconnect = code => this.OnRelayDisconnect(c, code);
|
||||||
await c.Connect();
|
await c.Connect();
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
15
packages/system/src/RelayMetricHandler.ts
Normal file
15
packages/system/src/RelayMetricHandler.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { FeedCache } from "@snort/shared";
|
||||||
|
import { Connection } from "Connection";
|
||||||
|
import { RelayMetrics } from "cache";
|
||||||
|
|
||||||
|
export class RelayMetricHandler {
|
||||||
|
readonly #cache: FeedCache<RelayMetrics>;
|
||||||
|
|
||||||
|
constructor(cache: FeedCache<RelayMetrics>) {
|
||||||
|
this.#cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
onDisconnect(c: Connection, code: number) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
22
packages/system/src/cache/RelayMetricCache.ts
vendored
Normal file
22
packages/system/src/cache/RelayMetricCache.ts
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { db, RelayMetrics } from ".";
|
||||||
|
import { FeedCache } from "@snort/shared";
|
||||||
|
|
||||||
|
export class RelayMetricCache extends FeedCache<RelayMetrics> {
|
||||||
|
constructor() {
|
||||||
|
super("RelayMetrics", db.relayMetrics);
|
||||||
|
}
|
||||||
|
|
||||||
|
key(of: RelayMetrics): string {
|
||||||
|
return of.addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
override async preload(): Promise<void> {
|
||||||
|
await super.preload();
|
||||||
|
// load everything
|
||||||
|
await this.buffer([...this.onTable]);
|
||||||
|
}
|
||||||
|
|
||||||
|
takeSnapshot(): Array<RelayMetrics> {
|
||||||
|
return [...this.cache.values()];
|
||||||
|
}
|
||||||
|
}
|
4
packages/system/src/cache/db.ts
vendored
4
packages/system/src/cache/db.ts
vendored
@ -3,11 +3,11 @@ import { NostrEvent } from "../Nostr";
|
|||||||
import Dexie, { Table } from "dexie";
|
import Dexie, { Table } from "dexie";
|
||||||
|
|
||||||
const NAME = "snort-system";
|
const NAME = "snort-system";
|
||||||
const VERSION = 1;
|
const VERSION = 2;
|
||||||
|
|
||||||
const STORES = {
|
const STORES = {
|
||||||
users: "++pubkey, name, display_name, picture, nip05, npub",
|
users: "++pubkey, name, display_name, picture, nip05, npub",
|
||||||
relays: "++addr",
|
relayMetrics: "++addr",
|
||||||
userRelays: "++pubkey",
|
userRelays: "++pubkey",
|
||||||
events: "++id, pubkey, created_at"
|
events: "++id, pubkey, created_at"
|
||||||
};
|
};
|
||||||
|
@ -25,6 +25,7 @@ export * from "./impl/nip44";
|
|||||||
export * from "./cache";
|
export * from "./cache";
|
||||||
export * from "./cache/UserRelayCache";
|
export * from "./cache/UserRelayCache";
|
||||||
export * from "./cache/UserCache";
|
export * from "./cache/UserCache";
|
||||||
|
export * from "./cache/RelayMetricCache";
|
||||||
|
|
||||||
export interface SystemInterface {
|
export interface SystemInterface {
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user