fix(search): replace stale records when saving an index (#2817)

This commit is contained in:
hhang
2026-10-16 11:57:01 +08:00
committed by GitHub
parent 7272bfa1fb
commit 2d8cb5a74c
2 changed files with 72 additions and 6 deletions
+11 -6
View File
@@ -20,7 +20,7 @@ db.version(1).stores({
expires: 'key, value',
});
async function saveData(maxAge, expireKey) {
async function saveData(maxAge, expireKey, indexKey) {
const records = [];
Object.values(INDEXES).forEach(entry => {
@@ -43,10 +43,15 @@ async function saveData(maxAge, expireKey) {
});
INDEXES = records;
await /** @type {any} */ (db).search.bulkPut(records);
await /** @type {any} */ (db).expires.put({
key: expireKey,
value: Date.now() + maxAge,
const searchTable = db.table('search');
const expiresTable = db.table('expires');
await db.transaction('rw', searchTable, expiresTable, async () => {
await searchTable.where({ indexKey }).delete();
await searchTable.bulkPut(records);
await expiresTable.put({
key: expireKey,
value: Date.now() + maxAge,
});
});
}
@@ -449,7 +454,7 @@ export async function init(config, vm) {
const markComplete = async () => {
if (len === ++count) {
await saveData(config.maxAge, expireKey);
await saveData(config.maxAge, expireKey, indexKey);
}
};
+61
View File
@@ -340,6 +340,67 @@ test.describe('Search Plugin Tests', () => {
await expect(resultsHeadingElm).toHaveText('EmptyContent');
});
test('does not restore deleted sections after rebuilding an expired cache', async ({
page,
}) => {
const options = {
config: {
search: { paths: ['/'], namespace: 'cache-refresh', maxAge: -1 },
},
markdown: { homepage: '# Obsolete\n\nretiredkeyword' },
scriptURLs: ['/dist/plugins/search.js'],
};
const searchField = page.locator('input[type=search]');
const results = page.locator('.results-panel .title');
await docsifyInit(options);
await searchField.fill('retiredkeyword');
await expect(results).toHaveText('Obsolete');
options.config.search.maxAge = 60000;
options.markdown.homepage = '# Current\n\ncurrentkeyword';
await docsifyInit(options);
await searchField.fill('currentkeyword');
await expect(results).toHaveText('Current');
await searchField.fill('retiredkeyword');
await expect(page.getByText('No Results!', { exact: true })).toBeVisible();
await docsifyInit(options);
await searchField.fill('currentkeyword');
await expect(results).toHaveText('Current');
await searchField.fill('retiredkeyword');
await expect(page.getByText('No Results!', { exact: true })).toBeVisible();
});
test('preserves another namespace when saving a search index', async ({
page,
}) => {
const otherSite = {
config: { search: { paths: ['/'], namespace: 'other-site' } },
markdown: { homepage: '# Other site\n\nprotectedkeyword' },
scriptURLs: ['/dist/plugins/search.js'],
};
const searchField = page.locator('input[type=search]');
const results = page.locator('.results-panel .title');
await docsifyInit(otherSite);
await searchField.fill('protectedkeyword');
await expect(results).toHaveText('Other site');
await docsifyInit({
config: { search: { paths: ['/'], namespace: 'current-site' } },
markdown: { homepage: '# Current site\n\ncurrentkeyword' },
scriptURLs: ['/dist/plugins/search.js'],
});
await searchField.fill('currentkeyword');
await expect(results).toHaveText('Current site');
otherSite.markdown.homepage = '# Changed\n\nchangedkeyword';
await docsifyInit(otherSite);
await searchField.fill('protectedkeyword');
await expect(results).toHaveText('Other site');
});
test('keeps saving index when one auto path request fails with cached records', async ({
page,
}) => {