Export event types from util, tweak feed interface

This commit is contained in:
Jon Staab
2024-04-15 15:25:07 -07:00
parent 1fcce21b58
commit 254074287d
7 changed files with 52 additions and 58 deletions
+8 -5
View File
@@ -14,12 +14,15 @@ const loader = new FeedLoader({
}) })
// Define a feed using set operations // Define a feed using set operations
const feed = intersection( const feed = intersectionFeed(
union( unionFeed(
dvm({kind: 5300, pubkey: '19b78ccfa7c5e31e6bacbb3f2a1703f64b62017702e584440bf29a7e16263e8c'}), dvmFeed({
list("10003:19ba654f26afd4930fd3d51baf4e26f1413b7aeec7190cd6c0cdf4d2f14cec6b:"), kind: 5300,
pubkey: '19b78ccfa7c5e31e6bacbb3f2a1703f64b62017702e584440bf29a7e16263e8c',
}),
listFeed("10003:19ba654f26afd4930fd3d51baf4e26f1413b7aeec7190cd6c0cdf4d2f14cec6b:"),
) )
filter({ filterFeed({
min_wot: 0.1, min_wot: 0.1,
scopes: ["global"], scopes: ["global"],
}), }),
+7 -7
View File
@@ -1,11 +1,11 @@
import {inc, uniq, now, isNil} from '@coracle.social/lib' import {inc, uniq, now, isNil} from '@coracle.social/lib'
import type {Rumor, Filter} from '@coracle.social/util' import type {Rumor, Filter} from '@coracle.social/util'
import {Tags, getIdFilters, mergeFilters} from '@coracle.social/util' import {Tags, getIdFilters, mergeFilters} from '@coracle.social/util'
import type {RequestItem, DVMItem, Scope, Feed, DynamicFilter, FeedContext} from './core' import type {RequestItem, DVMItem, Scope, Feed, DynamicFilter, FeedOptions} from './core'
import {FeedType} from './core' import {FeedType} from './core'
export class FeedCompiler<E extends Rumor> { export class FeedCompiler<E extends Rumor> {
constructor(readonly context: FeedContext<E>) {} constructor(readonly options: FeedOptions<E>) {}
walk([type, ...feed]: Feed, visit: (feed: Feed) => void) { walk([type, ...feed]: Feed, visit: (feed: Feed) => void) {
visit([type, ...feed] as Feed) visit([type, ...feed] as Feed)
@@ -88,7 +88,7 @@ export class FeedCompiler<E extends Rumor> {
async _compileLists(addresses: string[]): Promise<RequestItem> { async _compileLists(addresses: string[]): Promise<RequestItem> {
const events: E[] = [] const events: E[] = []
await this.context.request({ await this.options.request({
relays: [], relays: [],
filters: getIdFilters(addresses), filters: getIdFilters(addresses),
onEvent: events.push, onEvent: events.push,
@@ -103,7 +103,7 @@ export class FeedCompiler<E extends Rumor> {
async _compileLols(addresses: string[]): Promise<RequestItem> { async _compileLols(addresses: string[]): Promise<RequestItem> {
const events: E[] = [] const events: E[] = []
await this.context.request({ await this.options.request({
relays: [], relays: [],
filters: getIdFilters(addresses), filters: getIdFilters(addresses),
onEvent: events.push, onEvent: events.push,
@@ -117,7 +117,7 @@ export class FeedCompiler<E extends Rumor> {
await Promise.all( await Promise.all(
requests.map(request => requests.map(request =>
this.context.requestDvm({ this.options.requestDvm({
tags: [], tags: [],
...request, ...request,
onEvent: events.push, onEvent: events.push,
@@ -135,11 +135,11 @@ export class FeedCompiler<E extends Rumor> {
_compileFilter({scopes, min_wot, max_wot, until_ago, since_ago, ...filter}: DynamicFilter) { _compileFilter({scopes, min_wot, max_wot, until_ago, since_ago, ...filter}: DynamicFilter) {
if (scopes && !filter.authors) { if (scopes && !filter.authors) {
filter.authors = scopes.flatMap((scope: Scope) => this.context.getPubkeysForScope(scope)) filter.authors = scopes.flatMap((scope: Scope) => this.options.getPubkeysForScope(scope))
} }
if ((!isNil(min_wot) || !isNil(max_wot))) { if ((!isNil(min_wot) || !isNil(max_wot))) {
const authors = this.context.getPubkeysForWotRange(min_wot || 0, max_wot || 1) const authors = this.options.getPubkeysForWotRange(min_wot || 0, max_wot || 1)
if (filter.authors) { if (filter.authors) {
const authorsSet = new Set(authors) const authorsSet = new Set(authors)
+10 -10
View File
@@ -52,15 +52,15 @@ export type Feed =
LOLFeed | LOLFeed |
DVMFeed DVMFeed
export const usingRelays = (relays: string[], ...feeds: Feed[]) => [FeedType.Relay, relays, ...feeds] as Feed export const relayFeed = (relays: string[], ...feeds: Feed[]) => [FeedType.Relay, relays, ...feeds] as Feed
export const difference = (...feeds: Feed[]) => [FeedType.Difference, ...feeds] as Feed export const differenceFeed = (...feeds: Feed[]) => [FeedType.Difference, ...feeds] as Feed
export const intersection = (...feeds: Feed[]) => [FeedType.Intersection, ...feeds] as Feed export const intersectionFeed = (...feeds: Feed[]) => [FeedType.Intersection, ...feeds] as Feed
export const symmetricDifference = (...feeds: Feed[]) => [FeedType.SymmetricDifference, ...feeds] as Feed export const symmetricDifferenceFeed = (...feeds: Feed[]) => [FeedType.SymmetricDifference, ...feeds] as Feed
export const union = (...feeds: Feed[]) => [FeedType.Union, ...feeds] as Feed export const unionFeed = (...feeds: Feed[]) => [FeedType.Union, ...feeds] as Feed
export const filter = (...filters: DynamicFilter[]) => [FeedType.Filter, ...filters] as Feed export const filterFeed = (...filters: DynamicFilter[]) => [FeedType.Filter, ...filters] as Feed
export const list = (...addresses: string[]) => [FeedType.List, ...addresses] as Feed export const listFeed = (...addresses: string[]) => [FeedType.List, ...addresses] as Feed
export const lol = (...addresses: string[]) => [FeedType.LOL, ...addresses] as Feed export const lolFeed = (...addresses: string[]) => [FeedType.LOL, ...addresses] as Feed
export const dvm = (...requests: DVMItem[]) => [FeedType.DVM, ...requests] as Feed export const dvmFeed = (...requests: DVMItem[]) => [FeedType.DVM, ...requests] as Feed
export type RequestItem = { export type RequestItem = {
relays: string[] relays: string[]
@@ -80,7 +80,7 @@ export type DVMOpts<E> = DVMItem & {
onEvent: (event: E) => void onEvent: (event: E) => void
} }
export type FeedContext<E> = { export type FeedOptions<E> = {
request: (opts: RequestOpts<E>) => Promise<void> request: (opts: RequestOpts<E>) => Promise<void>
requestDvm: (opts: DVMOpts<E>) => Promise<void> requestDvm: (opts: DVMOpts<E>) => Promise<void>
getPubkeysForScope: (scope: Scope) => string[] getPubkeysForScope: (scope: Scope) => string[]
+25 -23
View File
@@ -1,13 +1,13 @@
import {inc, max, min, now, isNil} from '@coracle.social/lib' import {inc, max, min, now, isNil} from '@coracle.social/lib'
import type {Rumor, Filter} from '@coracle.social/util' import type {Rumor, Filter} from '@coracle.social/util'
import {Tags, EPOCH, getIdFilters, guessFilterDelta, mergeFilters} from '@coracle.social/util' import {Tags, EPOCH, getIdFilters, guessFilterDelta, mergeFilters} from '@coracle.social/util'
import type {Scope, Feed, DynamicFilter, RequestOpts, RequestItem, FeedContext} from './core' import type {Scope, Feed, DynamicFilter, RequestOpts, RequestItem, FeedOptions} from './core'
import {FeedType} from './core' import {FeedType} from './core'
import {FeedCompiler} from './compiler' import {FeedCompiler} from './compiler'
export type LoadOpts<E> = { export type LoadOpts<E> = {
onEvent: (event: E) => void onEvent?: (event: E) => void
onExhausted: () => void onExhausted?: () => void
} }
export type Loader = (limit: number) => Promise<void> export type Loader = (limit: number) => Promise<void>
@@ -15,8 +15,8 @@ export type Loader = (limit: number) => Promise<void>
export class FeedLoader<E extends Rumor> { export class FeedLoader<E extends Rumor> {
compiler: FeedCompiler<E> compiler: FeedCompiler<E>
constructor(readonly context: FeedContext<E>) { constructor(readonly options: FeedOptions<E>) {
this.compiler = new FeedCompiler(context) this.compiler = new FeedCompiler(options)
} }
async getLoader([type, ...feed]: Feed, loadOpts: LoadOpts<E>) { async getLoader([type, ...feed]: Feed, loadOpts: LoadOpts<E>) {
@@ -63,15 +63,17 @@ export class FeedLoader<E extends Rumor> {
let count = 0 let count = 0
await this.context.request({ if (requestFilters.length > 0) {
relays, await this.options.request({
filters: requestFilters, relays,
onEvent: (event: E) => { filters: requestFilters,
count += 1 onEvent: (event: E) => {
since = Math.min(since, event.created_at) count += 1
onEvent(event) until = Math.min(until, event.created_at)
}, onEvent?.(event)
}) },
})
}
// Relays can't be relied upon to return events in descending order, do exponential // Relays can't be relied upon to return events in descending order, do exponential
// windowing to ensure we get the most recent stuff on first load, but eventually find it all // windowing to ensure we get the most recent stuff on first load, but eventually find it all
@@ -82,7 +84,7 @@ export class FeedLoader<E extends Rumor> {
since = Math.max(minSince, since - delta) since = Math.max(minSince, since - delta)
if (since === minSince) { if (since === minSince) {
onExhausted() onExhausted?.()
} }
} }
} }
@@ -121,13 +123,13 @@ export class FeedLoader<E extends Rumor> {
for (const event of events.splice(0)) { for (const event of events.splice(0)) {
if (!skip.has(event.id) && !seen.has(event.id)) { if (!skip.has(event.id) && !seen.has(event.id)) {
onEvent(event) onEvent?.(event)
seen.add(event.id) seen.add(event.id)
} }
} }
if (exhausted.size === loaders.length) { if (exhausted.size === loaders.length) {
onExhausted() onExhausted?.()
} }
} }
} }
@@ -163,13 +165,13 @@ export class FeedLoader<E extends Rumor> {
for (const event of events.splice(0)) { for (const event of events.splice(0)) {
if (counts.get(event.id) === loaders.length && !seen.has(event.id)) { if (counts.get(event.id) === loaders.length && !seen.has(event.id)) {
onEvent(event) onEvent?.(event)
seen.add(event.id) seen.add(event.id)
} }
} }
if (exhausted.size === loaders.length) { if (exhausted.size === loaders.length) {
onExhausted() onExhausted?.()
} }
} }
} }
@@ -205,13 +207,13 @@ export class FeedLoader<E extends Rumor> {
for (const event of events.values()) { for (const event of events.values()) {
if (counts.get(event.id) === 1 && !seen.has(event.id)) { if (counts.get(event.id) === 1 && !seen.has(event.id)) {
onEvent(event) onEvent?.(event)
seen.add(event.id) seen.add(event.id)
} }
} }
if (exhausted.size === loaders.length) { if (exhausted.size === loaders.length) {
onExhausted() onExhausted?.()
} }
} }
} }
@@ -226,7 +228,7 @@ export class FeedLoader<E extends Rumor> {
onExhausted: () => exhausted.add(i), onExhausted: () => exhausted.add(i),
onEvent: (event: E) => { onEvent: (event: E) => {
if (!seen.has(event.id)) { if (!seen.has(event.id)) {
onEvent(event) onEvent?.(event)
seen.add(event.id) seen.add(event.id)
} }
}, },
@@ -246,7 +248,7 @@ export class FeedLoader<E extends Rumor> {
) )
if (exhausted.size === loaders.length) { if (exhausted.size === loaders.length) {
onExhausted() onExhausted?.()
} }
} }
} }
-12
View File
@@ -166,12 +166,6 @@ export const mergeSubscriptions = (subs: Subscription[]) => {
} }
} }
// console.log(
// `Starting ${mergedSubscriptions.length} subscriptions on ${uniq(mergedSubscriptions.flatMap(s => s.request.relays)).length} relays`,
// uniq(mergedSubscriptions.flatMap(s => s.request.relays)),
// ...mergeFilters(mergedSubscriptions.flatMap(s => s.request.filters)),
// )
return mergedSubscriptions return mergedSubscriptions
} }
@@ -265,12 +259,6 @@ export const subscribe = (request: SubscribeRequest) => {
} }
if (request.immediate) { if (request.immediate) {
// console.log(
// `Starting 1 subscriptions on ${request.relays.length} relays`,
// request.relays,
// ...mergeFilters(request.filters)
// )
executeSubscription(subscription) executeSubscription(subscription)
} else { } else {
executeSubscriptionBatched(subscription) executeSubscriptionBatched(subscription)
+1
View File
@@ -1,4 +1,5 @@
import type {Event, EventTemplate, UnsignedEvent} from 'nostr-tools' import type {Event, EventTemplate, UnsignedEvent} from 'nostr-tools'
export type {Event, EventTemplate, UnsignedEvent} from 'nostr-tools'
import {verifyEvent, getEventHash} from 'nostr-tools' import {verifyEvent, getEventHash} from 'nostr-tools'
import {cached, now} from '@coracle.social/lib' import {cached, now} from '@coracle.social/lib'
import {Tags} from './Tags' import {Tags} from './Tags'
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@coracle.social/util", "name": "@coracle.social/util",
"version": "0.0.7", "version": "0.0.8",
"author": "hodlbod", "author": "hodlbod",
"license": "MIT", "license": "MIT",
"description": "A collection of utilities.", "description": "A collection of utilities.",