Reduce storage writes during agent streaming (#3232)
* perf(app): skip transient replica cache writes The replica cache subscribed to the entire session store, so live stream-head updates forced repeated JSON serialization and browser storage writes even though the head is not persisted. Select the cache's persisted inputs once and schedule writes only when that projection changes. * test(app): move perf cleanup into fixture Keep the replica-cache performance scenario as a direct setup, stream, measure, and assert flow while the spec-local Playwright fixture owns deterministic mock-agent cleanup.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import type { WorkspaceDescriptorPayload } from "@getpaseo/protocol/messages";
|
||||
import { normalizeAgentSnapshot } from "@/utils/agent-snapshots";
|
||||
import {
|
||||
@@ -15,12 +15,14 @@ const LRU_SERVER_IDS = ["host-a", "host-b", "host-c"] as const;
|
||||
|
||||
class MemoryStorage implements ReplicaCacheStorage {
|
||||
readonly values = new Map<string, string>();
|
||||
writes = 0;
|
||||
|
||||
async getItem(key: string): Promise<string | null> {
|
||||
return this.values.get(key) ?? null;
|
||||
}
|
||||
|
||||
async setItem(key: string, value: string): Promise<void> {
|
||||
this.writes += 1;
|
||||
this.values.set(key, value);
|
||||
}
|
||||
}
|
||||
@@ -154,12 +156,39 @@ function seedTimeline(serverId: string, text: string): void {
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
const store = useSessionStore.getState();
|
||||
store.clearSession(SERVER_ID);
|
||||
for (const serverId of LRU_SERVER_IDS) store.clearSession(serverId);
|
||||
});
|
||||
|
||||
describe("ReplicaCache", () => {
|
||||
it("persists focused replica changes without writing transient stream head updates", async () => {
|
||||
vi.useFakeTimers();
|
||||
const storage = new MemoryStorage();
|
||||
const cache = new ReplicaCache(storage);
|
||||
cache.setHosts([SERVER_ID]);
|
||||
seedSession();
|
||||
await cache.flush();
|
||||
cache.start();
|
||||
const writesBeforeStream = storage.writes;
|
||||
|
||||
useSessionStore
|
||||
.getState()
|
||||
.setAgentStreamHead(SERVER_ID, new Map([["agent-1", [message("live", "Streaming")]]]));
|
||||
await vi.advanceTimersByTimeAsync(1_000);
|
||||
|
||||
expect(storage.writes).toBe(writesBeforeStream);
|
||||
|
||||
useSessionStore
|
||||
.getState()
|
||||
.setAgentStreamTail(SERVER_ID, new Map([["agent-1", [message("saved", "Committed")]]]));
|
||||
await vi.advanceTimersByTimeAsync(1_000);
|
||||
|
||||
expect(storage.writes).toBe(writesBeforeStream + 1);
|
||||
cache.setHosts([]);
|
||||
});
|
||||
|
||||
it("restores a displayable stale replica without claiming remote hydration", async () => {
|
||||
const storage = new MemoryStorage();
|
||||
const writer = new ReplicaCache(storage);
|
||||
|
||||
Reference in New Issue
Block a user