Remove direct query cache access and unused readers

This commit is contained in:
murashit 2026-07-10 13:15:34 +09:00
parent d9024ba983
commit 5f22d21dc7
6 changed files with 13 additions and 40 deletions

View file

@ -20,7 +20,6 @@ import {
activeThreadsQueryKey,
appServerMetadataQueryKey,
appServerModelsQueryKey,
appServerQueriesFilter,
appServerQueryContextIsComplete,
archivedThreadsQueryKey,
cloneAppServerQueryContext,
@ -52,7 +51,7 @@ type ThreadListKind = "active" | "archived";
type ThreadListUpdater = (threads: readonly Thread[] | null) => readonly Thread[] | null;
export class AppServerQueryCache {
readonly client: QueryClient;
private readonly client: QueryClient;
private readonly clientRunner: AppServerQueryClientRunner | null;
private readonly activeThreadCursors = new Map<string, string | null>();
@ -66,14 +65,6 @@ export class AppServerQueryCache {
this.client.clear();
}
clearContext(context: AppServerQueryContext): void {
if (!appServerQueryContextIsComplete(context)) return;
const filter = appServerQueriesFilter(context);
void this.client.cancelQueries(filter);
this.client.removeQueries(filter);
this.activeThreadCursors.delete(this.activeThreadCursorKey(context));
}
activeThreadsSnapshot(context: AppServerQueryContext): readonly Thread[] | null {
return this.threadListSnapshot(context, "active");
}

View file

@ -1,5 +1,3 @@
import type { QueryKey } from "@tanstack/query-core";
export interface AppServerQueryContext {
codexPath: string;
vaultPath: string;
@ -47,10 +45,6 @@ export function appServerModelsQueryKey(context: AppServerQueryContext): AppServ
return [...appServerQueryScope(context), "models"];
}
export function appServerQueriesFilter(context: AppServerQueryContext): { queryKey: QueryKey } {
return { queryKey: appServerQueryScope(context) };
}
function nonEmptyString(value: string): boolean {
return value.trim().length > 0;
}

View file

@ -56,10 +56,6 @@ export class AppServerSharedQueries {
return this.runForCurrentContext((context) => this.options.cache.loadMoreActiveThreads(context));
}
fetchArchivedThreads(): Promise<readonly Thread[]> {
return this.runForCurrentContext((context) => this.options.cache.fetchArchivedThreads(context));
}
refreshActiveThreads(): Promise<readonly Thread[]> {
return this.runForCurrentContext((context) => this.options.cache.refreshActiveThreads(context));
}

View file

@ -11,7 +11,6 @@ interface ThreadCatalogStore {
fetchAllActiveThreads(): Promise<readonly Thread[]>;
hasMoreActiveThreads(): boolean;
loadMoreActiveThreads(): Promise<readonly Thread[]>;
fetchArchivedThreads(): Promise<readonly Thread[]>;
refreshActiveThreads(): Promise<readonly Thread[]>;
refreshArchivedThreads(): Promise<readonly Thread[]>;
observeActiveThreadsResult(observer: ThreadListObserver, options?: { emitCurrent?: boolean }): () => void;
@ -73,7 +72,6 @@ export interface ThreadCatalogPaginatedActiveReader extends ThreadCatalogActiveR
export interface ThreadCatalogArchivedReader {
archivedSnapshot(): readonly Thread[] | null;
loadArchived(): Promise<readonly Thread[]>;
refreshArchived(): Promise<readonly Thread[]>;
observeArchived(observer: ThreadListObserver, options?: { emitCurrent?: boolean }): () => void;
}
@ -109,7 +107,6 @@ export function createThreadCatalog(options: ThreadCatalogOptions): ThreadCatalo
});
}, observeOptions),
archivedSnapshot: () => threadListProjection(store.archivedThreadsSnapshot(), currentFacts().archived),
loadArchived: () => loadThreadList(store.fetchArchivedThreads(), currentFacts().archived),
refreshArchived: () => loadThreadList(store.refreshArchivedThreads(), currentFacts().archived),
observeArchived: (observer, observeOptions) =>
store.observeArchivedThreadsResult((result) => {

View file

@ -17,10 +17,19 @@ import {
import type { SharedServerMetadata } from "../../src/domain/server/metadata";
describe("AppServerQueryCache", () => {
it("allows inactive query contexts to be garbage-collected", () => {
const cache = new AppServerQueryCache();
it("garbage-collects inactive query contexts", async () => {
vi.useFakeTimers();
try {
const cache = new AppServerQueryCache();
const context = cacheContext();
cache.setActiveThreads(context, [thread("temporary")]);
expect(cache.client.getDefaultOptions().queries?.gcTime).toBe(300_000);
await vi.advanceTimersByTimeAsync(300_001);
expect(cache.activeThreadsSnapshot(context)).toBeNull();
} finally {
vi.useRealTimers();
}
});
it("preserves successful metadata resource values when probes fail", () => {
@ -398,19 +407,6 @@ describe("AppServerQueryCache", () => {
expect(cache.appServerMetadataSnapshot(context)).toEqual(refreshed);
});
it("clears thread list snapshots by context", () => {
const cache = new AppServerQueryCache();
const context = cacheContext();
cache.setActiveThreads(context, [thread("thread")]);
expect(cache.activeThreadsSnapshot(context)).toEqual([thread("thread")]);
cache.clearContext(context);
expect(cache.activeThreadsSnapshot(context)).toBeNull();
});
it("does not merge local thread list updates into in-flight app-server snapshots", async () => {
const context = cacheContext();
const refresh = deferred<readonly ReturnType<typeof thread>[]>();

View file

@ -1107,7 +1107,6 @@ function settingsTabHost(
};
const threadCatalog = {
archivedSnapshot: vi.fn(() => options.archivedSnapshot ?? null),
loadArchived: vi.fn().mockResolvedValue(options.archivedThreads ?? defaultArchivedThreads),
refreshArchived: options.refreshArchived ?? vi.fn().mockResolvedValue(options.archivedThreads ?? defaultArchivedThreads),
observeArchived: options.observeArchived ?? vi.fn(() => () => undefined),
apply: options.applyThreadCatalogEvent ?? vi.fn(),