Skip to content

refactor: use new_search to create CancellationToken for search#192

Open
hsqStephenZhang wants to merge 6 commits intomasterfrom
refactor/search-cancel/token
Open

refactor: use new_search to create CancellationToken for search#192
hsqStephenZhang wants to merge 6 commits intomasterfrom
refactor/search-cancel/token

Conversation

@hsqStephenZhang
Copy link
Copy Markdown
Collaborator

Fix

fix #191

Goal

let search-cache decide if the version is outdated since there is only a global counter.

Solution

  1. update the search-cancel to provide a new api that fetch_and_add(counter, 1)
  2. update the payload definition to make sure frontend is aware of the cancelation.

Test

via observation that there is no anomaly

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors search cancellation/versioning so the backend owns the global search version counter (instead of the frontend supplying versions), and updates the IPC payload to represent cancelled searches explicitly.

Changes:

  • Add CancellationToken::new_search() (auto-increments global search version) and expose CancellationToken::version().
  • Update the Tauri search command to use new_search() and serialize cancelled searches as results: null / Option<Vec<_>>.
  • Update frontend IPC types and hook logic to treat results: null as a cancelled search.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

File Description
search-cancel/src/lib.rs Adds backend-owned search token creation + version accessor.
cardinal/src-tauri/src/commands.rs Switches search command to backend-owned cancellation/versioning and nullable results.
cardinal/src/types/ipc.ts Updates IPC payload typing to allow results: null for cancellation.
cardinal/src/hooks/useFileSearch.ts Stops sending version, and ignores cancelled/stale responses.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread search-cancel/src/lib.rs Outdated
Comment on lines +35 to +37
/// create a token for search, different with `CancellationToken::new`
/// it uses global version's current version number
/// user don't need to specify a version number
Comment thread search-cancel/src/lib.rs
Comment on lines +38 to +44
pub fn new_search() -> Self {
let version = self::ACTIVE_SEARCH_VERSION.fetch_add(1, Ordering::SeqCst) + 1;
Self {
version,
active_version: &ACTIVE_SEARCH_VERSION,
}
}
Comment thread cardinal/src/hooks/useFileSearch.ts Outdated
Comment on lines 241 to 243
if (rawResults.results === null || searchVersionRef.current !== requestVersion) {
return;
}
Comment on lines 208 to 212
#[derive(Serialize, Default)]
pub struct SearchResponse {
pub results: Vec<SlabIndex>,
pub results: Option<Vec<SlabIndex>>,
pub highlights: Vec<String>,
}
Comment thread cardinal/src/types/ipc.ts
Comment on lines 28 to 31
export type SearchResponsePayload = {
results: number[];
// null means search is cancelled
results: number[] | null;
highlights?: string[];
Comment thread cardinal/src/hooks/useFileSearch.ts Outdated
Comment on lines 241 to 244
if (rawResults.results === null || searchVersionRef.current !== requestVersion) {
return;
}

@hsqStephenZhang
Copy link
Copy Markdown
Collaborator Author

seems that i don't have the permission to let copilot re-review the code.

@ldm0
Copy link
Copy Markdown
Member

ldm0 commented May 1, 2026

@hsqStephenZhang You need a copilot pro subscription :-P
Not worth it though.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors search cancellation/versioning so the backend owns the global search version and the frontend can detect cancelled searches via an explicit status code in the search response.

Changes:

  • Added CancellationToken::new_search() (auto-increments global search version) and a version() accessor.
  • Updated Tauri search command to use new_search() and return a status_code indicating OK/ERROR/CANCELLED.
  • Updated frontend IPC types, useFileSearch hook, and tests to use the new status_code field and remove the request version parameter.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
search-cancel/src/lib.rs Adds new_search() + version() and expands cancellation tests.
cardinal/src-tauri/src/commands.rs Switches search cancellation to backend-managed versioning; adds status_code to response.
cardinal/src/types/ipc.ts Introduces SearchStatusCode and adds status_code to SearchResponsePayload.
cardinal/src/hooks/useFileSearch.ts Stops sending version; ignores cancelled results using status_code.
cardinal/src/hooks/tests/useFileSearch.test.ts Updates mocks to include status_code and adds a cancelled-search test.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread cardinal/src/types/ipc.ts Outdated
export type SearchResponsePayload = {
results: number[];
highlights?: string[];
status_code: SearchStatusCode;
Comment on lines 208 to +213
#[derive(Serialize, Default)]
pub struct SearchResponse {
pub results: Vec<SlabIndex>,
pub highlights: Vec<String>,
pub status_code: u8,
}
Comment on lines +245 to +256
if (
rawResults.status_code === SearchStatusCode.CANCELLED ||
searchVersionRef.current !== requestVersion
) {
return;
}

const searchResults = rawResults.results as SlabIndex[];
const highlightTerms = Array.isArray(rawResults.highlights)
? rawResults.highlights.filter((term): term is string => typeof term === 'string')
: [];

Comment on lines 294 to 304
}) {
error!("Failed to send search request: {e:?}");
return Ok(SearchResponse::default());
return Ok(SearchResponse::new_error());
}

match result_rx.recv() {
Ok(res) => res,
Err(e) => {
error!("Failed to receive search result: {e:?}");
return Ok(SearchResponse::default());
return Ok(SearchResponse::new_error());
}
Comment on lines +44 to +78
it('ignores results when backend returns null (cancelled)', async () => {
const initialResults = [1, 2, 3] as SlabIndex[];

mockedInvoke.mockImplementation((command: string) => {
if (command === 'get_app_status') {
return Promise.resolve('Ready');
}
if (command === 'search') {
// First call (initial search) returns results
return Promise.resolve({
results: initialResults,
highlights: [],
status_code: SearchStatusCode.OK,
});
}
return Promise.resolve(null);
});

const { result } = renderHook(() => useFileSearch());

// Wait for initial search to complete
await waitFor(() => expect(result.current.state.initialFetchCompleted).toBe(true));
expect(result.current.state.results).toBe(initialResults);

// Mock search to return null for the next call
mockedInvoke.mockImplementation((command: string) => {
if (command === 'search') {
return Promise.resolve({
results: [],
highlights: [],
status_code: SearchStatusCode.CANCELLED,
});
}
return Promise.resolve('Ready');
});
Comment thread search-cancel/src/lib.rs Outdated
Comment on lines +181 to +193

#[test]
fn search_token_cancelled_after_new_search_version2() {
let _guard = lock_versions();
reset_versions();

let search_v1 = CancellationToken::new_search();
assert!(search_v1.is_cancelled().is_some());

let search_v2 = CancellationToken::new_search();
assert!(search_v2.is_cancelled().is_some());
assert!(search_v1.is_cancelled().is_none()); // search_v1 is now cancelled
}
Comment thread search-cancel/src/lib.rs
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors Cardinal’s search cancellation to be backend-owned by introducing CancellationToken::new_search() (auto-incrementing a global search version), and updates the IPC contract so the frontend can distinguish “cancelled” from “successful” search results.

Changes:

  • Add CancellationToken::new_search() and update Rust tests to use it instead of passing frontend-managed versions.
  • Extend search IPC response with statusCode (OK vs CANCELLED) and update the React hook + tests to consume it.
  • Update Tauri search command to create cancellation tokens internally and propagate cancellation via statusCode.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
search-cancel/tests/more.rs Updates cancellation tests to use CancellationToken::new_search().
search-cancel/src/lib.rs Introduces new_search() and exposes version(); adds/updates token behavior tests.
search-cache/tests/query_matrix_big.rs Updates cancellation test to use new_search().
search-cache/tests/edge_cases_comprehensive.rs Updates cancellation-related tests to use new_search().
search-cache/tests/content_filter_comprehensive.rs Updates cancellation test setup to use new_search().
search-cache/tests/boundary_limits_tests.rs Updates cancellation tests to use new_search().
search-cache/src/tests/traversal.rs Updates cancellation test to use new_search().
search-cache/src/tests/date_volume.rs Switches a “no cancellation” token to new_search() (now risky under parallel tests).
search-cache/src/cache.rs Updates unit tests that simulate cancellation to use new_search().
namepool/tests/fuzz_large.rs Updates cancellation simulation to use new_search().
namepool/src/lib.rs Updates unit tests to use new_search() for cancellation.
doc/inner/ui-dataflow.md Updates UI/backend dataflow documentation for backend-owned cancellation and statusCode.
doc/inner/search-cancellation.md Updates cancellation docs to reference new_search().
cardinal/src/types/ipc.ts Adds SearchStatusCode enum and makes statusCode required on search response payload.
cardinal/src/hooks/useFileSearch.ts Removes version parameter from search invoke; ignores cancelled responses via statusCode.
cardinal/src/hooks/tests/useFileSearch.test.ts Updates existing test payload shape and adds a CANCELLED-handling test.
cardinal/src-tauri/src/commands.rs Removes version arg from search command, uses new_search(), returns statusCode, and errors on channel failures.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread search-cancel/src/lib.rs Outdated

pub fn new(version: u64) -> Self {
ACTIVE_SEARCH_VERSION.store(version, Ordering::SeqCst);
/// Creates a token for a search, unlike `CancellationToken::new`.
let _ = cache.search("dm:thisyear").unwrap();
// ensure no cancellation
let token = CancellationToken::new(9999); // never cancelled
let token = CancellationToken::new_search(); // never cancelled
Comment on lines +248 to 254
if (
rawResults.statusCode === SearchStatusCode.CANCELLED ||
searchVersionRef.current !== requestVersion
) {
return;
}

Comment on lines +83 to +87
// The results should still be the initial results, not updated or cleared
// We wait a bit to ensure it had time to process if it were going to
await new Promise((resolve) => setTimeout(resolve, 50));
expect(result.current.state.results).toBe(initialResults);
expect(result.current.state.currentQuery).toBe(''); // Query doesn't update on cancelled search
@hsqStephenZhang hsqStephenZhang force-pushed the refactor/search-cancel/token branch from 5d5d911 to cf9c7b5 Compare May 2, 2026 08:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[refactor] new_search api for CancellationToken

3 participants