search: cache results
This commit is contained in:
@@ -185,6 +185,18 @@ type CreateChatRequest = {
|
||||
messages?: CompletionRequestMessage[];
|
||||
};
|
||||
|
||||
type CreateSearchRequest = {
|
||||
title?: string;
|
||||
query?: string;
|
||||
reuseByQuery?: boolean;
|
||||
};
|
||||
|
||||
type CreateSearchResponse = {
|
||||
search: SearchSummary;
|
||||
reused: boolean;
|
||||
cacheHit: boolean;
|
||||
};
|
||||
|
||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? "/api";
|
||||
const ENV_ADMIN_TOKEN = (import.meta.env.VITE_ADMIN_TOKEN as string | undefined)?.trim() || null;
|
||||
let authToken: string | null = ENV_ADMIN_TOKEN;
|
||||
@@ -296,14 +308,22 @@ export async function listSearches() {
|
||||
return data.searches;
|
||||
}
|
||||
|
||||
export async function createSearch(body?: { title?: string; query?: string }) {
|
||||
const data = await api<{ search: SearchSummary }>("/v1/searches", {
|
||||
async function postSearch(body?: CreateSearchRequest) {
|
||||
return api<CreateSearchResponse>("/v1/searches", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(body ?? {}),
|
||||
});
|
||||
}
|
||||
|
||||
export async function createSearch(body?: CreateSearchRequest) {
|
||||
const data = await postSearch(body);
|
||||
return data.search;
|
||||
}
|
||||
|
||||
export async function createReusableSearch(body: Omit<CreateSearchRequest, "reuseByQuery">) {
|
||||
return postSearch({ ...body, reuseByQuery: true });
|
||||
}
|
||||
|
||||
export async function getSearch(searchId: string) {
|
||||
const data = await api<{ search: SearchDetail }>(`/v1/searches/${searchId}`);
|
||||
return data.search;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { AuthScreen } from "@/components/auth/auth-screen";
|
||||
import { SearchResultsPanel } from "@/components/search/search-results-panel";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { createSearch, runSearchStream, type SearchDetail } from "@/lib/api";
|
||||
import { createReusableSearch, getSearch, runSearchStream, type SearchDetail } from "@/lib/api";
|
||||
import { useSessionAuth } from "@/hooks/use-session-auth";
|
||||
|
||||
function readQueryFromUrl() {
|
||||
@@ -85,14 +85,16 @@ export default function SearchRoutePage() {
|
||||
|
||||
const runQuery = async (query: string) => {
|
||||
const trimmed = query.trim();
|
||||
const requestId = ++requestCounterRef.current;
|
||||
streamAbortRef.current?.abort();
|
||||
|
||||
if (!trimmed) {
|
||||
setSearch(null);
|
||||
setError(null);
|
||||
setIsRunning(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const requestId = ++requestCounterRef.current;
|
||||
streamAbortRef.current?.abort();
|
||||
const abortController = new AbortController();
|
||||
streamAbortRef.current = abortController;
|
||||
let wasInterrupted = false;
|
||||
@@ -119,10 +121,11 @@ export default function SearchRoutePage() {
|
||||
});
|
||||
|
||||
try {
|
||||
const created = await createSearch({
|
||||
const createdResult = await createReusableSearch({
|
||||
query: trimmed,
|
||||
title: trimmed.slice(0, 80),
|
||||
});
|
||||
const created = createdResult.search;
|
||||
if (requestId !== requestCounterRef.current) return;
|
||||
|
||||
setSearch((current) =>
|
||||
@@ -140,6 +143,13 @@ export default function SearchRoutePage() {
|
||||
: current
|
||||
);
|
||||
|
||||
if (createdResult.cacheHit) {
|
||||
const cached = await getSearch(created.id);
|
||||
if (requestId !== requestCounterRef.current) return;
|
||||
setSearch(cached);
|
||||
return;
|
||||
}
|
||||
|
||||
await runSearchStream(
|
||||
created.id,
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user