| ... | @@ -365,6 +365,7 @@ export const make = Effect.fn("WorkspaceSearchIndex.make")(function* ( | ... | @@ -365,6 +365,7 @@ export const make = Effect.fn("WorkspaceSearchIndex.make")(function* ( |
| 365 | catch: (cause) => new WorkspaceSearchIndexDestroyFailed({ cwd, cause }), | 365 | catch: (cause) => new WorkspaceSearchIndexDestroyFailed({ cwd, cause }), |
| 366 | }).pipe(Effect.orDie), | 366 | }).pipe(Effect.orDie), |
| 367 | ); | 367 | ); |
| | 368 | let initialScanTimedOut = false; |
| 368 | yield* waitForIndexReady( | 369 | yield* waitForIndexReady( |
| 369 | cwd, | 370 | cwd, |
| 370 | finder, | 371 | finder, |
| ... | @@ -374,8 +375,18 @@ export const make = Effect.fn("WorkspaceSearchIndex.make")(function* ( | ... | @@ -374,8 +375,18 @@ export const make = Effect.fn("WorkspaceSearchIndex.make")(function* ( |
| 374 | reason, | 375 | reason, |
| 375 | cause, | 376 | cause, |
| 376 | }), | 377 | }), |
| | 378 | ).pipe( |
| | 379 | Effect.catchTag("WorkspaceSearchIndexScanTimedOut", (error) => |
| | 380 | variant === "paths" |
| | 381 | ? Effect.sync(() => { |
| | 382 | initialScanTimedOut = true; |
| | 383 | }) |
| | 384 | : Effect.fail(error), |
| | 385 | ), |
| 377 | ); | 386 | ); |
| 378 | | 387 | |
| | 388 | const hasIncompleteInitialScan = () => initialScanTimedOut && finder.isScanning(); |
| | 389 | |
| 379 | const runSearch = Effect.fn("WorkspaceSearchIndex.runSearch")(function* <A>( | 390 | const runSearch = Effect.fn("WorkspaceSearchIndex.runSearch")(function* <A>( |
| 380 | query: string, | 391 | query: string, |
| 381 | pageSize: number, | 392 | pageSize: number, |
| ... | @@ -436,6 +447,7 @@ export const make = Effect.fn("WorkspaceSearchIndex.make")(function* ( | ... | @@ -436,6 +447,7 @@ export const make = Effect.fn("WorkspaceSearchIndex.make")(function* ( |
| 436 | | 447 | |
| 437 | const list: WorkspaceSearchIndex["Service"]["list"] = Effect.fn("WorkspaceSearchIndex.list")( | 448 | const list: WorkspaceSearchIndex["Service"]["list"] = Effect.fn("WorkspaceSearchIndex.list")( |
| 438 | function* () { | 449 | function* () { |
| | 450 | const incompleteBeforeQuery = hasIncompleteInitialScan(); |
| 439 | const result = yield* runSearch("", WORKSPACE_INDEX_PAGE_SIZE, "mixedSearch", () => | 451 | const result = yield* runSearch("", WORKSPACE_INDEX_PAGE_SIZE, "mixedSearch", () => |
| 440 | finder.mixedSearch("", { pageSize: WORKSPACE_INDEX_PAGE_SIZE }), | 452 | finder.mixedSearch("", { pageSize: WORKSPACE_INDEX_PAGE_SIZE }), |
| 441 | ); | 453 | ); |
| ... | @@ -446,7 +458,8 @@ export const make = Effect.fn("WorkspaceSearchIndex.make")(function* ( | ... | @@ -446,7 +458,8 @@ export const make = Effect.fn("WorkspaceSearchIndex.make")(function* ( |
| 446 | const entries = sortedEntries.slice(0, WORKSPACE_INDEX_MAX_ENTRIES); | 458 | const entries = sortedEntries.slice(0, WORKSPACE_INDEX_MAX_ENTRIES); |
| 447 | return { | 459 | return { |
| 448 | entries, | 460 | entries, |
| 449 | truncated: mapped.truncated || entries.length < sortedEntries.length, | 461 | truncated: |
| | 462 | incompleteBeforeQuery || mapped.truncated || entries.length < sortedEntries.length, |
| 450 | }; | 463 | }; |
| 451 | }, | 464 | }, |
| 452 | ); | 465 | ); |
| ... | @@ -455,22 +468,26 @@ export const make = Effect.fn("WorkspaceSearchIndex.make")(function* ( | ... | @@ -455,22 +468,26 @@ export const make = Effect.fn("WorkspaceSearchIndex.make")(function* ( |
| 455 | "WorkspaceSearchIndex.search", | 468 | "WorkspaceSearchIndex.search", |
| 456 | )(function* (query, limit, kind, imageOnly) { | 469 | )(function* (query, limit, kind, imageOnly) { |
| 457 | const pageSize = imageOnly ? WORKSPACE_INDEX_PAGE_SIZE : Math.max(1, limit + 1); | 470 | const pageSize = imageOnly ? WORKSPACE_INDEX_PAGE_SIZE : Math.max(1, limit + 1); |
| | 471 | const incompleteBeforeQuery = hasIncompleteInitialScan(); |
| 458 | if (kind === "file" || imageOnly) { | 472 | if (kind === "file" || imageOnly) { |
| 459 | const result = yield* runSearch(query, pageSize, "fileSearch", () => | 473 | const result = yield* runSearch(query, pageSize, "fileSearch", () => |
| 460 | finder.fileSearch(query, { pageSize }), | 474 | finder.fileSearch(query, { pageSize }), |
| 461 | ); | 475 | ); |
| 462 | return mapFileSearchResult(result, limit, imageOnly); | 476 | const mapped = mapFileSearchResult(result, limit, imageOnly); |
| | 477 | return { ...mapped, truncated: incompleteBeforeQuery || mapped.truncated }; |
| 463 | } | 478 | } |
| 464 | if (kind === "directory") { | 479 | if (kind === "directory") { |
| 465 | const result = yield* runSearch(query, pageSize, "directorySearch", () => | 480 | const result = yield* runSearch(query, pageSize, "directorySearch", () => |
| 466 | finder.directorySearch(query, { pageSize }), | 481 | finder.directorySearch(query, { pageSize }), |
| 467 | ); | 482 | ); |
| 468 | return mapDirectorySearchResult(result, limit); | 483 | const mapped = mapDirectorySearchResult(result, limit); |
| | 484 | return { ...mapped, truncated: incompleteBeforeQuery || mapped.truncated }; |
| 469 | } | 485 | } |
| 470 | const result = yield* runSearch(query, pageSize, "mixedSearch", () => | 486 | const result = yield* runSearch(query, pageSize, "mixedSearch", () => |
| 471 | finder.mixedSearch(query, { pageSize }), | 487 | finder.mixedSearch(query, { pageSize }), |
| 472 | ); | 488 | ); |
| 473 | return mapMixedSearchResult(result, limit); | 489 | const mapped = mapMixedSearchResult(result, limit); |
| | 490 | return { ...mapped, truncated: incompleteBeforeQuery || mapped.truncated }; |
| 474 | }); | 491 | }); |
| 475 | | 492 | |
| 476 | const searchContents: WorkspaceSearchIndex["Service"]["searchContents"] = Effect.fn( | 493 | const searchContents: WorkspaceSearchIndex["Service"]["searchContents"] = Effect.fn( |