Add paging and limits to nostr video subscription

This commit is contained in:
thePR0M3TH3AN committed 2026-01-02 14:11:41 -05:00
1 parent 0302b3cde6
commit ff07ed8e01
2 files changed
+83 -9

No files matched your search

+66 -4
View File
@@ -301,6 +301,8 @@ function shouldRequestExtensionPermissions(signer) {
const EVENTS_CACHE_STORAGE_KEY = "bitvid:eventsCache:v1";
const LEGACY_EVENTS_STORAGE_KEY = "bitvidEvents";
const EVENTS_CACHE_TTL_MS = 10 * 60 * 1000; // 10 minutes
const DEFAULT_VIDEO_REQUEST_LIMIT = 150;
const MAX_VIDEO_REQUEST_LIMIT = 500;
// To limit error spam
let errorLogCount = 0;
@@ -5148,19 +5150,79 @@ export class NostrClient {
}
}
clampVideoRequestLimit(limit, fallback = DEFAULT_VIDEO_REQUEST_LIMIT) {
const normalizedFallback =
Number.isFinite(fallback) && fallback > 0
? Math.floor(fallback)
: DEFAULT_VIDEO_REQUEST_LIMIT;
if (!Number.isFinite(limit) || limit <= 0) {
return normalizedFallback;
}
const floored = Math.floor(limit);
const clamped = Math.min(MAX_VIDEO_REQUEST_LIMIT, Math.max(1, floored));
if (clamped !== floored && isDevMode) {
devLogger.log(
`[nostr] Clamped video request limit from ${floored} to ${clamped}`,
);
}
return clamped;
}
getLatestCachedCreatedAt() {
let latest = 0;
for (const video of this.allEvents.values()) {
const createdAt = Number.isFinite(video?.created_at)
? Math.floor(video.created_at)
: 0;
if (createdAt > latest) {
latest = createdAt;
}
}
return latest;
}
/**
* Subscribe to *all* videos (old and new) with a single subscription,
* buffering incoming events to avoid excessive DOM updates.
*
* @param {Function} onVideo
* @param {{ since?: number, until?: number, limit?: number }} [options]
* `since` defaults to the latest cached created_at to avoid replaying
* the full history on every load. `limit` is clamped to
* MAX_VIDEO_REQUEST_LIMIT.
*/
subscribeVideos(onVideo) {
subscribeVideos(onVideo, options = {}) {
const { since, until, limit } = options;
const latestCachedCreatedAt = this.getLatestCachedCreatedAt();
const resolvedLimit = this.clampVideoRequestLimit(limit);
const resolvedSince = Number.isFinite(since)
? Math.floor(since)
: latestCachedCreatedAt > 0
? latestCachedCreatedAt
: undefined;
const resolvedUntil = Number.isFinite(until) ? Math.floor(until) : undefined;
const filter = {
kinds: [30078],
"#t": ["video"],
// Adjust limit/time as desired
limit: 500,
since: 0,
limit: resolvedLimit,
};
if (resolvedSince !== undefined) {
filter.since = resolvedSince;
}
if (resolvedUntil !== undefined) {
filter.until = resolvedUntil;
}
devLogger.log("[subscribeVideos] Subscribing with filter:", filter);
const sub = this.pool.sub(this.relays, [filter]);
+17 -5
View File
@@ -1122,10 +1122,19 @@ export class NostrService {
this.resolveInitialLoad({ videos: initial, reason: "cache" });
if (!getStoredVideoSubscription()) {
const subscription = this.nostrClient.subscribeVideos(() => {
const updated = this.nostrClient.getActiveVideos();
applyAndNotify(updated, "subscription");
});
const subscriptionOptions = {
// Start from the freshest cached timestamp to avoid replaying the full history;
// use loadOlderVideos when the user scrolls for backfill.
since: this.nostrClient.getLatestCachedCreatedAt() || undefined,
limit: this.nostrClient.clampVideoRequestLimit(200),
};
const subscription = this.nostrClient.subscribeVideos(
() => {
const updated = this.nostrClient.getActiveVideos();
applyAndNotify(updated, "subscription");
},
subscriptionOptions,
);
this.setVideoSubscription(subscription);
this.emit("subscription:started", { subscription });
}
@@ -1160,11 +1169,14 @@ export class NostrService {
return [];
}
const clampedLimit =
this.nostrClient?.clampVideoRequestLimit(limit) ?? limit ?? 0;
const filter = {
kinds: [VIDEO_KIND],
"#t": ["video"],
until,
limit,
limit: clampedLimit,
};
const collected = new Map();