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
This commit is contained in:
Jacob Fletcher
2025-08-28 16:12:35 -04:00
committed by GitHub
parent 426f99ca99
commit b99c324f1e
3 changed files with 46 additions and 24 deletions

View File

@@ -149,7 +149,8 @@ export const generateReindexHandler =
await initTransaction(req)
for (const collection of collections) {
try {
const promises = collections.map(async (collection) => {
try {
await deleteIndexes(collection)
await reindexCollection(collection)
@@ -158,8 +159,13 @@ export const generateReindexHandler =
payload.logger.error({ err, msg: message })
await killTransaction(req)
return Response.json({ message }, { headers, status: 500 })
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', {

View File

@@ -494,20 +494,22 @@ describe('@payloadcms/plugin-search', () => {
})
it('should reindex whole collections', async () => {
await payload.create({
await Promise.all([
payload.create({
collection: pagesSlug,
data: {
title: 'Test page title',
_status: 'published',
},
})
await payload.create({
}),
payload.create({
collection: postsSlug,
data: {
title: 'Test page title',
_status: 'published',
},
})
}),
])
await wait(200)

View File

@@ -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<T extends boolean = true> {
hash?: T;
loginAttempts?: T;
lockUntil?: T;
sessions?:
| T
| {
id?: T;
createdAt?: T;
expiresAt?: T;
};
}
/**
* This interface was referenced by `Config`'s JSON-Schema