bug: always write relay list to bootstrap relays

This commit is contained in:
Kieran 2023-01-21 17:55:49 +00:00
parent 079b4ff9a9
commit abeb2f5a6c
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
4 changed files with 61 additions and 4 deletions

View File

@ -6,7 +6,7 @@ import Tag from "Nostr/Tag";
import { RootState } from "State/Store"; import { RootState } from "State/Store";
import { HexKey, RawEvent, u256, UserMetadata } from "Nostr"; import { HexKey, RawEvent, u256, UserMetadata } from "Nostr";
import { bech32ToHex } from "Util" import { bech32ToHex } from "Util"
import { HashtagRegex } from "Const"; import { DefaultRelays, HashtagRegex } from "Const";
declare global { declare global {
interface Window { interface Window {
@ -72,6 +72,18 @@ export default function useEventPublisher() {
System.BroadcastEvent(ev); System.BroadcastEvent(ev);
} }
}, },
/**
* Write event to DefaultRelays, this is important for profiles / relay lists to prevent bugs
* If a user removes all the DefaultRelays from their relay list and saves that relay list,
* When they open the site again we wont see that updated relay list and so it will appear to reset back to the previous state
*/
broadcastForBootstrap: (ev: NEvent | undefined) => {
if(ev) {
for(let [k, _] of DefaultRelays) {
System.WriteOnceToRelay(k, ev);
}
}
},
metadata: async (obj: UserMetadata) => { metadata: async (obj: UserMetadata) => {
if (pubKey) { if (pubKey) {
let ev = NEvent.ForPubKey(pubKey); let ev = NEvent.ForPubKey(pubKey);

View File

@ -5,7 +5,7 @@ import { Subscriptions } from "Nostr/Subscriptions";
import { default as NEvent } from "Nostr/Event"; import { default as NEvent } from "Nostr/Event";
import { DefaultConnectTimeout } from "Const"; import { DefaultConnectTimeout } from "Const";
import { ConnectionStats } from "Nostr/ConnectionStats"; import { ConnectionStats } from "Nostr/ConnectionStats";
import { RawEvent, TaggedRawEvent } from "Nostr"; import { RawEvent, TaggedRawEvent, u256 } from "Nostr";
export type CustomHook = (state: Readonly<StateSnapshot>) => void; export type CustomHook = (state: Readonly<StateSnapshot>) => void;
@ -44,6 +44,7 @@ export default class Connection {
LastState: Readonly<StateSnapshot>; LastState: Readonly<StateSnapshot>;
IsClosed: boolean; IsClosed: boolean;
ReconnectTimer: ReturnType<typeof setTimeout> | null; ReconnectTimer: ReturnType<typeof setTimeout> | null;
EventsCallback: Map<u256, () => void>;
constructor(addr: string, options: RelaySettings) { constructor(addr: string, options: RelaySettings) {
this.Address = addr; this.Address = addr;
@ -67,6 +68,7 @@ export default class Connection {
this.LastState = Object.freeze({ ...this.CurrentState }); this.LastState = Object.freeze({ ...this.CurrentState });
this.IsClosed = false; this.IsClosed = false;
this.ReconnectTimer = null; this.ReconnectTimer = null;
this.EventsCallback = new Map();
this.Connect(); this.Connect();
} }
@ -138,6 +140,12 @@ export default class Connection {
case "OK": { case "OK": {
// feedback to broadcast call // feedback to broadcast call
console.debug("OK: ", msg); console.debug("OK: ", msg);
const id = msg[1];
if (this.EventsCallback.has(id)) {
let cb = this.EventsCallback.get(id)!;
this.EventsCallback.delete(id);
cb();
}
break; break;
} }
case "NOTICE": { case "NOTICE": {
@ -170,6 +178,30 @@ export default class Connection {
this._UpdateState(); this._UpdateState();
} }
/**
* Send event on this connection and wait for OK response
*/
async SendAsync(e: NEvent, timeout: number = 5000) {
return new Promise<void>((resolve, reject) => {
if (!this.Settings.write) {
resolve();
return;
}
let t = setTimeout(() => {
resolve();
}, timeout);
this.EventsCallback.set(e.Id, () => {
clearTimeout(t);
resolve();
});
let req = ["EVENT", e.ToObject()];
this._SendJson(req);
this.Stats.EventsSent++;
this._UpdateState();
});
}
/** /**
* Subscribe to data from this connection * Subscribe to data from this connection
*/ */

View File

@ -50,6 +50,9 @@ export class NostrSystem {
for (let [_, s] of this.Subscriptions) { for (let [_, s] of this.Subscriptions) {
c.AddSubscription(s); c.AddSubscription(s);
} }
} else {
// update settings if already connected
this.Sockets.get(address)!.Settings = options;
} }
} catch (e) { } catch (e) {
console.error(e); console.error(e);
@ -90,6 +93,15 @@ export class NostrSystem {
} }
} }
/**
* Write an event to a relay then disconnect
*/
async WriteOnceToRelay(address: string, ev: Event) {
let c = new Connection(address, { write: true, read: false });
await c.SendAsync(ev);
c.Close();
}
/** /**
* Request profile metadata for a set of pubkeys * Request profile metadata for a set of pubkeys
*/ */
@ -179,9 +191,9 @@ export class NostrSystem {
let profile = mapEventToProfile(e); let profile = mapEventToProfile(e);
if (profile) { if (profile) {
let existing = await db.users.get(profile.pubkey); let existing = await db.users.get(profile.pubkey);
if((existing?.created ?? 0) < profile.created) { if ((existing?.created ?? 0) < profile.created) {
await db.users.put(profile); await db.users.put(profile);
} else if(existing) { } else if (existing) {
await db.users.update(profile.pubkey, { loaded: new Date().getTime() }); await db.users.update(profile.pubkey, { loaded: new Date().getTime() });
} }
} }

View File

@ -16,6 +16,7 @@ const RelaySettingsPage = () => {
async function saveRelays() { async function saveRelays() {
let ev = await publisher.saveRelays(); let ev = await publisher.saveRelays();
publisher.broadcast(ev); publisher.broadcast(ev);
publisher.broadcastForBootstrap(ev);
} }