From b99c324f1e24a13ce8e6aec735b91dabd3e3516f Mon Sep 17 00:00:00 2001 From: Jacob Fletcher Date: Thu, 28 Aug 2025 16:12:35 -0400 Subject: [PATCH] perf(plugin-search): reindex collections in parallel, up to 80% faster (#13608) Reindexing all collections in the search plugin was previously done in sequence which is slow and risks timing out under certain network conditions. By running these requests in parallel we are able to save **on average ~80%** in compute time. This test includes reindexing 2000 documents in total across 2 collections, 3 times over. The indexes themselves are relatively simple, containing only a couple simple fields each, so the savings would only increase with more complexity and/or more documents. Before: Attempt 1: 38434.87ms Attempt 2: 47852.61ms Attempt 3: 28407.79ms Avg: 38231.75ms After: Attempt 1: 7834.29ms Attempt 2: 7744.40ms Attempt 3: 7918.58ms Avg: 7832.42ms Total savings: ~79.51% --- - To see the specific tasks where the Asana app for GitHub is being used, see below: - https://app.asana.com/0/0/1211162504205343 --- .../src/utilities/generateReindexHandler.ts | 26 +++++++++------- test/plugin-search/int.spec.ts | 30 ++++++++++--------- test/plugin-search/payload-types.ts | 14 +++++++++ 3 files changed, 46 insertions(+), 24 deletions(-) diff --git a/packages/plugin-search/src/utilities/generateReindexHandler.ts b/packages/plugin-search/src/utilities/generateReindexHandler.ts index 5ec0700f7..c10ad0caa 100644 --- a/packages/plugin-search/src/utilities/generateReindexHandler.ts +++ b/packages/plugin-search/src/utilities/generateReindexHandler.ts @@ -149,17 +149,23 @@ export const generateReindexHandler = await initTransaction(req) - for (const collection of collections) { - try { - await deleteIndexes(collection) - await reindexCollection(collection) - } catch (err) { - const message = t('error:unableToReindexCollection', { collection }) - payload.logger.error({ err, msg: message }) + try { + const promises = collections.map(async (collection) => { + try { + await deleteIndexes(collection) + await reindexCollection(collection) + } catch (err) { + const message = t('error:unableToReindexCollection', { collection }) + payload.logger.error({ err, msg: message }) - await killTransaction(req) - return Response.json({ message }, { headers, status: 500 }) - } + await killTransaction(req) + throw new Error(message) + } + }) + + await Promise.all(promises) + } catch (err: any) { + return Response.json({ message: err.message }, { headers, status: 500 }) } const message = t('general:successfullyReindexed', { diff --git a/test/plugin-search/int.spec.ts b/test/plugin-search/int.spec.ts index 1271d46f2..80e2a6e5b 100644 --- a/test/plugin-search/int.spec.ts +++ b/test/plugin-search/int.spec.ts @@ -494,20 +494,22 @@ describe('@payloadcms/plugin-search', () => { }) it('should reindex whole collections', async () => { - await payload.create({ - collection: pagesSlug, - data: { - title: 'Test page title', - _status: 'published', - }, - }) - await payload.create({ - collection: postsSlug, - data: { - title: 'Test page title', - _status: 'published', - }, - }) + await Promise.all([ + payload.create({ + collection: pagesSlug, + data: { + title: 'Test page title', + _status: 'published', + }, + }), + payload.create({ + collection: postsSlug, + data: { + title: 'Test page title', + _status: 'published', + }, + }), + ]) await wait(200) diff --git a/test/plugin-search/payload-types.ts b/test/plugin-search/payload-types.ts index 595bad643..7478e3766 100644 --- a/test/plugin-search/payload-types.ts +++ b/test/plugin-search/payload-types.ts @@ -136,6 +136,13 @@ export interface User { hash?: string | null; loginAttempts?: number | null; lockUntil?: string | null; + sessions?: + | { + id: string; + createdAt?: string | null; + expiresAt: string; + }[] + | null; password?: string | null; } /** @@ -300,6 +307,13 @@ export interface UsersSelect { hash?: T; loginAttempts?: T; lockUntil?: T; + sessions?: + | T + | { + id?: T; + createdAt?: T; + expiresAt?: T; + }; } /** * This interface was referenced by `Config`'s JSON-Schema