Add simplifyFeed
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import {inc, memoize, omitVals, max, min, now} from "@welshman/lib"
|
import {inc, defer, Deferred, memoize, omitVals, max, min, now} from "@welshman/lib"
|
||||||
import {EPOCH, trimFilters, guessFilterDelta, TrustedEvent, Filter} from "@welshman/util"
|
import {EPOCH, trimFilters, guessFilterDelta, TrustedEvent, Filter} from "@welshman/util"
|
||||||
import {Feed, FeedType, RequestItem} from "./core.js"
|
import {Feed, FeedType, RequestItem} from "./core.js"
|
||||||
import {FeedCompiler, FeedCompilerOptions} from "./compiler.js"
|
import {FeedCompiler, FeedCompilerOptions} from "./compiler.js"
|
||||||
@@ -87,17 +87,17 @@ export class FeedController {
|
|||||||
const minSince = sinces.length === filters.length ? min(sinces) : EPOCH
|
const minSince = sinces.length === filters.length ? min(sinces) : EPOCH
|
||||||
const initialDelta = guessFilterDelta(filters)
|
const initialDelta = guessFilterDelta(filters)
|
||||||
|
|
||||||
let loading = false
|
let promise: Deferred<void> | undefined
|
||||||
let delta = initialDelta
|
let delta = initialDelta
|
||||||
let since = this.options.useWindowing ? maxUntil - delta : minSince
|
let since = this.options.useWindowing ? maxUntil - delta : minSince
|
||||||
let until = maxUntil
|
let until = maxUntil
|
||||||
|
|
||||||
return async (limit: number) => {
|
return async (limit: number) => {
|
||||||
if (loading) {
|
if (promise) {
|
||||||
return
|
return promise
|
||||||
}
|
}
|
||||||
|
|
||||||
loading = true
|
promise = defer()
|
||||||
|
|
||||||
const requestFilters = filters!
|
const requestFilters = filters!
|
||||||
// Remove filters that don't fit our window
|
// Remove filters that don't fit our window
|
||||||
@@ -148,32 +148,31 @@ export class FeedController {
|
|||||||
onExhausted?.()
|
onExhausted?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
loading = false
|
promise.resolve()
|
||||||
|
promise = undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getDifferenceLoader(feeds: Feed[]) {
|
_getDifferenceLoader(feeds: Feed[]) {
|
||||||
const exhausted = new Set<number>()
|
const exhausted = new Set<number>()
|
||||||
const skip = new Set<string>()
|
const skip = new Set<string>()
|
||||||
const events: TrustedEvent[] = []
|
const events: TrustedEvent[] = []
|
||||||
const seen = new Set()
|
const seen = new Set()
|
||||||
|
|
||||||
const controllers = await Promise.all(
|
const controllers = feeds.map(
|
||||||
feeds.map(
|
(thisFeed: Feed, i: number) =>
|
||||||
(thisFeed: Feed, i: number) =>
|
new FeedController({
|
||||||
new FeedController({
|
...this.options,
|
||||||
...this.options,
|
feed: thisFeed,
|
||||||
feed: thisFeed,
|
onExhausted: () => exhausted.add(i),
|
||||||
onExhausted: () => exhausted.add(i),
|
onEvent: (event: TrustedEvent) => {
|
||||||
onEvent: (event: TrustedEvent) => {
|
if (i === 0) {
|
||||||
if (i === 0) {
|
events.push(event)
|
||||||
events.push(event)
|
} else {
|
||||||
} else {
|
skip.add(event.id)
|
||||||
skip.add(event.id)
|
}
|
||||||
}
|
},
|
||||||
},
|
}),
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return async (limit: number) => {
|
return async (limit: number) => {
|
||||||
@@ -200,25 +199,23 @@ export class FeedController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getIntersectionLoader(feeds: Feed[]) {
|
_getIntersectionLoader(feeds: Feed[]) {
|
||||||
const exhausted = new Set<number>()
|
const exhausted = new Set<number>()
|
||||||
const counts = new Map<string, number>()
|
const counts = new Map<string, number>()
|
||||||
const events: TrustedEvent[] = []
|
const events: TrustedEvent[] = []
|
||||||
const seen = new Set()
|
const seen = new Set()
|
||||||
|
|
||||||
const controllers = await Promise.all(
|
const controllers = feeds.map(
|
||||||
feeds.map(
|
(thisFeed: Feed, i: number) =>
|
||||||
(thisFeed: Feed, i: number) =>
|
new FeedController({
|
||||||
new FeedController({
|
...this.options,
|
||||||
...this.options,
|
feed: thisFeed,
|
||||||
feed: thisFeed,
|
onExhausted: () => exhausted.add(i),
|
||||||
onExhausted: () => exhausted.add(i),
|
onEvent: (event: TrustedEvent) => {
|
||||||
onEvent: (event: TrustedEvent) => {
|
events.push(event)
|
||||||
events.push(event)
|
counts.set(event.id, inc(counts.get(event.id)))
|
||||||
counts.set(event.id, inc(counts.get(event.id)))
|
},
|
||||||
},
|
}),
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return async (limit: number) => {
|
return async (limit: number) => {
|
||||||
@@ -245,25 +242,23 @@ export class FeedController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getUnionLoader(feeds: Feed[]) {
|
_getUnionLoader(feeds: Feed[]) {
|
||||||
const exhausted = new Set<number>()
|
const exhausted = new Set<number>()
|
||||||
const seen = new Set()
|
const seen = new Set()
|
||||||
|
|
||||||
const controllers = await Promise.all(
|
const controllers = feeds.map(
|
||||||
feeds.map(
|
(thisFeed: Feed, i: number) =>
|
||||||
(thisFeed: Feed, i: number) =>
|
new FeedController({
|
||||||
new FeedController({
|
...this.options,
|
||||||
...this.options,
|
feed: thisFeed,
|
||||||
feed: thisFeed,
|
onExhausted: () => exhausted.add(i),
|
||||||
onExhausted: () => exhausted.add(i),
|
onEvent: (event: TrustedEvent) => {
|
||||||
onEvent: (event: TrustedEvent) => {
|
if (!seen.has(event.id)) {
|
||||||
if (!seen.has(event.id)) {
|
this.options.onEvent?.(event)
|
||||||
this.options.onEvent?.(event)
|
seen.add(event.id)
|
||||||
seen.add(event.id)
|
}
|
||||||
}
|
},
|
||||||
},
|
}),
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return async (limit: number) => {
|
return async (limit: number) => {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {now, uniq, displayList} from "@welshman/lib"
|
import {now, uniq, displayList, formatTimestampAsDate, formatTimestampRelative} from "@welshman/lib"
|
||||||
import {
|
import {
|
||||||
FeedType,
|
FeedType,
|
||||||
Feed,
|
Feed,
|
||||||
@@ -42,13 +42,19 @@ export const displayCreatedAtFeed = (feed: CreatedAtFeed) => {
|
|||||||
const parts: string[] = []
|
const parts: string[] = []
|
||||||
|
|
||||||
if (since) {
|
if (since) {
|
||||||
const timestamp = relative.includes("since") ? now() - since : since
|
if (relative.includes("since")) {
|
||||||
parts.push(`after ${new Date(timestamp * 1000).toLocaleString()}`)
|
parts.push(`after ${formatTimestampRelative(now() - since)}`)
|
||||||
|
} else {
|
||||||
|
parts.push(`after ${formatTimestampAsDate(since)}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (until) {
|
if (until) {
|
||||||
const timestamp = relative.includes("until") ? now() - until : until
|
if (relative.includes("until")) {
|
||||||
parts.push(`before ${new Date(timestamp * 1000).toLocaleString()}`)
|
parts.push(`before ${formatTimestampRelative(now() - until)}`)
|
||||||
|
} else {
|
||||||
|
parts.push(`before ${formatTimestampAsDate(until)}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parts.length > 0) {
|
if (parts.length > 0) {
|
||||||
|
|||||||
@@ -206,3 +206,61 @@ export const walkFeed = (feed: Feed, visit: (feed: Feed) => void) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const simplifyFeed = (feed: Feed): Feed => {
|
||||||
|
if (isUnionFeed(feed)) {
|
||||||
|
const args = getFeedArgs(feed)
|
||||||
|
|
||||||
|
if (args.length === 1) return simplifyFeed(args[0])
|
||||||
|
|
||||||
|
const modified: Feed[] = []
|
||||||
|
|
||||||
|
for (let sub of args.map(simplifyFeed)) {
|
||||||
|
if (isUnionFeed(sub)) {
|
||||||
|
modified.push(...getFeedArgs(sub))
|
||||||
|
} else {
|
||||||
|
modified.push(sub)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return makeUnionFeed(...modified)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isIntersectionFeed(feed)) {
|
||||||
|
const args = getFeedArgs(feed)
|
||||||
|
|
||||||
|
if (args.length === 1) return simplifyFeed(args[0])
|
||||||
|
|
||||||
|
const modified: Feed[] = []
|
||||||
|
|
||||||
|
for (let sub of args.map(simplifyFeed)) {
|
||||||
|
if (isIntersectionFeed(sub)) {
|
||||||
|
modified.push(...getFeedArgs(sub))
|
||||||
|
} else {
|
||||||
|
modified.push(sub)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return makeIntersectionFeed(...modified)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDifferenceFeed(feed)) {
|
||||||
|
const args = getFeedArgs(feed)
|
||||||
|
|
||||||
|
if (args.length === 1) return simplifyFeed(args[0])
|
||||||
|
|
||||||
|
const modified: Feed[] = []
|
||||||
|
|
||||||
|
for (let sub of args.map(simplifyFeed)) {
|
||||||
|
if (isDifferenceFeed(sub)) {
|
||||||
|
modified.push(...getFeedArgs(sub))
|
||||||
|
} else {
|
||||||
|
modified.push(sub)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return makeDifferenceFeed(...modified)
|
||||||
|
}
|
||||||
|
|
||||||
|
return feed
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user