···3030 static readonly MAX_POSTS: number = 100;
31313232 /**
3333+ * Number of posts to request per-user per fetch.
3434+ * Keeps individual requests small to improve latency.
3535+ * @default 5
3636+ */
3737+ static readonly POSTS_BATCH_SIZE: number = 5;
3838+3939+ /**
4040+ * Number of accounts to fetch per getNextPosts invocation.
4141+ * This spaces work across multiple infinite-scroll calls.
4242+ * @default 10
4343+ */
4444+ static readonly ACCOUNTS_PER_BATCH: number = 10;
4545+4646+ /**
3347 * Footer text for the dashboard, you probably want to change this. Supports HTML.
3448 * @default "<a href='https://git.witchcraft.systems/scientific-witchery/pds-dash' target='_blank'>Source</a> (<a href='https://github.com/witchcraft-systems/pds-dash/' target='_blank'>github mirror</a>)"
3549 */
+33-6
src/lib/pdsfetch.ts
···2828}
29293030let accountsMetadata: AccountMetadata[] = [];
3131+let accountFetchIndex = 0;
3232+let initialFetchDone = false;
31333234interface atUriObject {
3335 repo: string;
···316318 if (!accountsMetadata.length) {
317319 accountsMetadata = await getAllMetadataFromPds();
318320 }
321321+ if (!accountsMetadata.length) {
322322+ return [];
323323+ }
324324+ // Fetch posts for a subset of accounts (batch) to reduce per-call load
325325+ const accountsPerBatch = Config.ACCOUNTS_PER_BATCH || 10;
326326+ let accountsToFetch: AccountMetadata[];
319327320320- // Fetch posts for all accounts
328328+ // On the first fetch, query all accounts but with a small per-account limit
329329+ if (!initialFetchDone) {
330330+ accountsToFetch = accountsMetadata.slice();
331331+ initialFetchDone = true;
332332+ } else {
333333+ const start = accountFetchIndex;
334334+ const end = start + accountsPerBatch;
335335+ if (end <= accountsMetadata.length) {
336336+ accountsToFetch = accountsMetadata.slice(start, end);
337337+ } else {
338338+ accountsToFetch = accountsMetadata.slice(start).concat(
339339+ accountsMetadata.slice(0, end % accountsMetadata.length),
340340+ );
341341+ }
342342+343343+ // Advance the rotating index for the next invocation
344344+ accountFetchIndex = (accountFetchIndex + accountsToFetch.length) % accountsMetadata.length;
345345+ }
346346+321347 const postsAcc: PostsAcc[] = await Promise.all(
322322- accountsMetadata.map(async (account) => {
348348+ accountsToFetch.map(async (account) => {
323349 const result = await fetchPostsForUser(
324350 account.did,
325325- account.currentCursor || null
351351+ account.currentCursor || null,
352352+ Config.POSTS_BATCH_SIZE,
326353 );
327354328355 const records = result?.records ?? [];
···336363 posts: records,
337364 account,
338365 };
339339- })
366366+ }),
340367 );
341368342369 // Flatten posts
···388415 }
389416};
390417391391-const fetchPostsForUser = async (did: At.Did, cursor: string | null) => {
418418+const fetchPostsForUser = async (did: At.Did, cursor: string | null, limit: number = Config.POSTS_BATCH_SIZE) => {
392419 try {
393420 const { data } = await rpc.get("com.atproto.repo.listRecords", {
394421 params: {
395422 repo: did as At.Identifier,
396423 collection: "app.bsky.feed.post",
397397- limit: Config.MAX_POSTS,
424424+ limit: limit,
398425 cursor: cursor || undefined,
399426 },
400427 });