Support rumors in thunks

This commit is contained in:
Jon Staab
2024-10-08 13:20:43 -07:00
parent da05362bf1
commit a4085af9e3
3 changed files with 59 additions and 29 deletions
+7 -1
View File
@@ -12,7 +12,7 @@ export const collection = <T, LoadArgs extends any[]>({
name: string
store: Readable<T[]>
getKey: (item: T) => string
load: (key: string, ...args: LoadArgs) => Promise<any>
load?: (key: string, ...args: LoadArgs) => Promise<any>
}) => {
const indexStore = withGetter(derived(store, $items => indexBy(getKey, $items)))
const pending = new Map<string, Promise<Maybe<T>>>()
@@ -20,6 +20,12 @@ export const collection = <T, LoadArgs extends any[]>({
const loadItem = async (key: string, ...args: LoadArgs) => {
const stale = indexStore.get().get(key)
// If we have no loader function, nothing we can do
if (!load) {
return stale
}
const freshness = getFreshness(name, key)
// If we have an item, reload if it's stale
+49 -26
View File
@@ -1,7 +1,8 @@
import {writable, get} from 'svelte/store'
import {Worker, assoc} from '@welshman/lib'
import {stamp, own, hash} from "@welshman/signer"
import type {HashedEvent, EventTemplate, SignedEvent} from '@welshman/util'
import type {TrustedEvent, HashedEvent, EventTemplate, SignedEvent, StampedEvent, OwnedEvent} from '@welshman/util'
import {isStampedEvent, isOwnedEvent, isHashedEvent, isUnwrappedEvent, isSignedEvent} from '@welshman/util'
import {publish, PublishStatus} from "@welshman/net"
import {repository, tracker} from './core'
import {pubkey, getSession, getSigner} from './session'
@@ -20,7 +21,7 @@ export type PublishStatusDataByUrlById = Record<string, PublishStatusDataByUrl>
export const publishStatusData = writable<PublishStatusDataByUrlById>({})
export type Thunk = {
event: HashedEvent
event: TrustedEvent
relays: string[]
}
@@ -31,31 +32,45 @@ export type ThunkWithResolve = Thunk & {
export const thunkWorker = new Worker<ThunkWithResolve>()
thunkWorker.addGlobalHandler(async ({event, relays, resolve}: ThunkWithResolve) => {
const session = getSession(event.pubkey)
if (!session) {
return console.warn(`No session found for ${event.pubkey}`)
// If we were given a wrapped event, make sure to publish the wrapper, not the rumor
if (isUnwrappedEvent(event)) {
event = event.wrap
}
const signedEvent = await getSigner(session)!.sign(event)
// If the event was already signed, leave it alone. Otherwise, sign it now. This is to
// decrease apparent latency in the UI that results from waiting for remote signers
if (!isSignedEvent(event)) {
const signer = getSigner(getSession(event.pubkey))
if (!signer) {
return console.warn(`No signer found for ${event.pubkey}`)
}
event = await signer.sign(event)
}
// We're guaranteed to have a signed event at this point
const signedEvent = event as SignedEvent
const {id, sig} = signedEvent
// Send it off
const pub = publish({event: signedEvent, relays})
// Copy the signature over since we had deferred it
const savedEvent = repository.getEvent(signedEvent.id) as SignedEvent
const savedEvent = repository.getEvent(id) as SignedEvent
// The event may already be replaced or deleted
if (savedEvent) {
savedEvent.sig = signedEvent.sig
savedEvent.sig = sig
}
// Track publish success
const {id} = event
const statusByUrl: PublishStatusDataByUrl = {}
pub.emitter.on("*", (status: PublishStatus, url: string, message: string) => {
publishStatusData.update(
assoc(id, Object.assign(statusByUrl, {[url]: {id, url, status, message}})),
)
Object.assign(statusByUrl, {[url]: {id, url, status, message}})
publishStatusData.update(assoc(id, statusByUrl))
if (status === PublishStatus.Success) {
tracker.track(id, url)
@@ -70,23 +85,31 @@ thunkWorker.addGlobalHandler(async ({event, relays, resolve}: ThunkWithResolve)
})
})
export type ThunkParams = {
event: EventTemplate
relays: string[]
}
export type ThunkEvent = EventTemplate | StampedEvent | OwnedEvent | TrustedEvent
export const makeThunk = ({event, relays}: ThunkParams) => {
const $pubkey = get(pubkey)
if (!$pubkey) {
throw new Error("Unable to make thunk if no user is logged in")
export const prepEvent = (event: ThunkEvent) => {
if (!isStampedEvent(event as StampedEvent)) {
event = stamp(event)
}
return {event: hash(own(stamp(event), $pubkey)), relays}
if (!isOwnedEvent(event as OwnedEvent)) {
event = own(event as StampedEvent, get(pubkey)!)
}
if (!isHashedEvent(event as HashedEvent)) {
event = hash(event as OwnedEvent)
}
return event as TrustedEvent
}
export const publishThunk = (thunk: Thunk) =>
export const makeThunk = ({event, relays}: {event: ThunkEvent, relays: string[]}) =>
({event, relays})
export const publishThunk = ({event, relays}: Thunk) =>
new Promise<PublishStatusDataByUrl>(resolve => {
thunkWorker.push({...thunk, resolve})
repository.publish(thunk.event)
event = prepEvent(event)
thunkWorker.push({event, relays, resolve})
repository.publish(event)
})
+3 -2
View File
@@ -1,5 +1,6 @@
import {parseJson, append, nthNe, nthEq} from "@welshman/lib"
import {Address} from "./Address"
import {uniqTags} from "./Tags"
import {isShareableRelayUrl} from "./Relay"
import {Encryptable, DecryptedEvent} from "./Encryptable"
import type {EncryptableUpdates} from "./Encryptable"
@@ -63,7 +64,7 @@ export const addToListPublicly = (list: List, tag: string[]) => {
const template = {
kind: list.kind,
content: list.event?.content || "",
tags: append(tag, list.publicTags),
tags: uniqTags(append(tag, list.publicTags)),
}
return new Encryptable(template, {})
@@ -76,6 +77,6 @@ export const addToListPrivately = (list: List, tag: string[]) => {
}
return new Encryptable(template, {
content: JSON.stringify(append(tag, list.privateTags)),
content: JSON.stringify(uniqTags(append(tag, list.privateTags))),
})
}