fix(search): "Clear cached index" was undone immediately by the active search re-persisting its in-memory rows (#184 O4)
CI / Build & Quality Checks (push) Successful in 1m50s
CI / Docker image build & smoke test (push) Skipped
CI / Secret scan (gitleaks) (push) Successful in 33s
CI / Trigger Desktop Build (push) Successful in 7s
CI / Playwright smoke (e2e) (push) Successful in 2m2s
CI / Build & Quality Checks (push) Successful in 1m50s
CI / Docker image build & smoke test (push) Skipped
CI / Secret scan (gitleaks) (push) Successful in 33s
CI / Trigger Desktop Build (push) Successful in 7s
CI / Playwright smoke (e2e) (push) Successful in 2m2s
Clearing bumps cacheVersion so the search re-runs, and the re-run wrote the scanned rows straight back to IndexedDB, so the index was never empty while the button was visible. Skip persistence for that one re-run. Verified: IDB stores go to 0/0 after Clear; logout still deletes the DB. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
@@ -246,8 +246,15 @@ export function MessageSearch({
|
|||||||
const [cacheVersion, setCacheVersion] = useState(0);
|
const [cacheVersion, setCacheVersion] = useState(0);
|
||||||
const handleCacheLoaded = useCallback(() => setCacheVersion((v) => v + 1), []);
|
const handleCacheLoaded = useCallback(() => setCacheVersion((v) => v + 1), []);
|
||||||
// Explicit wipe of the persistent on-disk index, then re-run the merge.
|
// Explicit wipe of the persistent on-disk index, then re-run the merge.
|
||||||
|
// After a clear, the active search re-runs (cacheVersion) and would persist
|
||||||
|
// the in-memory rows straight back — skip that one write so "Clear cached
|
||||||
|
// index" actually leaves the disk empty until the next new search.
|
||||||
|
const skipPersistOnceRef = useRef(false);
|
||||||
const handleClearSearchCache = useCallback(() => {
|
const handleClearSearchCache = useCallback(() => {
|
||||||
clearSearchCache().then(() => setCacheVersion((v) => v + 1));
|
clearSearchCache().then(() => {
|
||||||
|
skipPersistOnceRef.current = true;
|
||||||
|
setCacheVersion((v) => v + 1);
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// The rooms actually in scope for this search (mirrors server-side logic)
|
// The rooms actually in scope for this search (mirrors server-side logic)
|
||||||
@@ -277,12 +284,15 @@ export function MessageSearch({
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
|
const persist = !skipPersistOnceRef.current;
|
||||||
|
skipPersistOnceRef.current = false;
|
||||||
searchLocalMessages({
|
searchLocalMessages({
|
||||||
term: msgSearchParams.term ?? '',
|
term: msgSearchParams.term ?? '',
|
||||||
roomIds: localSearchRooms,
|
roomIds: localSearchRooms,
|
||||||
senders: msgSearchParams.senders,
|
senders: msgSearchParams.senders,
|
||||||
fromTs: msgSearchParams.fromTs,
|
fromTs: msgSearchParams.fromTs,
|
||||||
toTs: msgSearchParams.toTs,
|
toTs: msgSearchParams.toTs,
|
||||||
|
persist,
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
if (!cancelled) setLocalResult(result);
|
if (!cancelled) setLocalResult(result);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,6 +18,12 @@ export type LocalSearchParams = {
|
|||||||
/** Optional date-range filter (ms). Applied to both memory and cached rows. */
|
/** Optional date-range filter (ms). Applied to both memory and cached rows. */
|
||||||
fromTs?: number;
|
fromTs?: number;
|
||||||
toTs?: number;
|
toTs?: number;
|
||||||
|
/**
|
||||||
|
* Set false to run the scan without writing it back to IndexedDB — used
|
||||||
|
* right after "Clear cached index" so the clear is not undone by the
|
||||||
|
* re-run of the active search (Gitea #184 O4).
|
||||||
|
*/
|
||||||
|
persist?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LocalSearchResult = {
|
export type LocalSearchResult = {
|
||||||
@@ -149,6 +155,7 @@ export const useLocalMessageSearch = () => {
|
|||||||
senders,
|
senders,
|
||||||
fromTs,
|
fromTs,
|
||||||
toTs,
|
toTs,
|
||||||
|
persist = true,
|
||||||
}: LocalSearchParams): Promise<LocalSearchResult> => {
|
}: LocalSearchParams): Promise<LocalSearchResult> => {
|
||||||
const trimmedTerm = term.trim();
|
const trimmedTerm = term.trim();
|
||||||
const senderSet = senders && senders.length > 0 ? new Set(senders) : null;
|
const senderSet = senders && senders.length > 0 ? new Set(senders) : null;
|
||||||
@@ -302,7 +309,7 @@ export const useLocalMessageSearch = () => {
|
|||||||
// Fire-and-forget persist of freshly scanned rows + coverage.
|
// Fire-and-forget persist of freshly scanned rows + coverage.
|
||||||
// saveRoomIndex swallows all errors internally, so a floating promise
|
// saveRoomIndex swallows all errors internally, so a floating promise
|
||||||
// here can never reject.
|
// here can never reject.
|
||||||
if (cacheEnabled && rowsToPersist.length > 0) {
|
if (cacheEnabled && persist && rowsToPersist.length > 0) {
|
||||||
saveRoomIndex(roomId, rowsToPersist);
|
saveRoomIndex(roomId, rowsToPersist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user