Merge branch 'perf/lag': dashboard lag fixes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> # Conflicts: # client/src/components/Sagi/PetSprite.tsx # client/src/components/Sagi/useSagiBrain.ts
This commit is contained in:
@@ -475,11 +475,31 @@ function sessionOutline(sessionId) {
|
||||
};
|
||||
}
|
||||
|
||||
// Each open chat polls its outline every few seconds, and building it parses
|
||||
// every tool event of the session: keep the last answer per session until its
|
||||
// events change (a new id, or fewer rows after a cleanup).
|
||||
const outlineStamp = db.prepare(
|
||||
"SELECT MAX(id) AS max_id, COUNT(*) AS n FROM events WHERE session_id = ?"
|
||||
);
|
||||
const OUTLINE_CACHE_MAX = 100;
|
||||
const outlineCache = new Map();
|
||||
function cachedOutline(sessionId) {
|
||||
const st = outlineStamp.get(sessionId);
|
||||
const stamp = `${st.max_id}:${st.n}`;
|
||||
const hit = outlineCache.get(sessionId);
|
||||
if (hit && hit.stamp === stamp) return hit.body;
|
||||
const body = sessionOutline(sessionId);
|
||||
outlineCache.delete(sessionId);
|
||||
outlineCache.set(sessionId, { stamp, body });
|
||||
if (outlineCache.size > OUTLINE_CACHE_MAX) outlineCache.delete(outlineCache.keys().next().value);
|
||||
return body;
|
||||
}
|
||||
|
||||
router.get("/:id/outline", (req, res) => {
|
||||
if (!stmts.getSession.get(req.params.id)) {
|
||||
return res.status(404).json({ error: { code: "NOT_FOUND", message: "Session not found" } });
|
||||
}
|
||||
res.json(sessionOutline(req.params.id));
|
||||
res.json(cachedOutline(req.params.id));
|
||||
});
|
||||
|
||||
// An image the session's own Read tool returned (`?path=`, exact), for the Chat
|
||||
@@ -1187,10 +1207,13 @@ router.get("/:id/transcript", async (req, res) => {
|
||||
}
|
||||
|
||||
if (afterLine !== null) {
|
||||
// Incremental mode: skip lines until after afterLine, collect up to limit, then stop
|
||||
let foundStart = false;
|
||||
// Incremental mode: skip lines until after afterLine, collect up to limit, then stop.
|
||||
// A line the client already has is skipped BEFORE it is parsed: every open
|
||||
// chat tails its transcript every few seconds, and parsing the whole JSONL
|
||||
// (MBs for a long session) each time was most of the server's steady CPU.
|
||||
for await (const line of rl) {
|
||||
lineNum++;
|
||||
if (lineNum <= afterLine) continue;
|
||||
if (!line.trim()) continue;
|
||||
let entry;
|
||||
try {
|
||||
@@ -1200,11 +1223,6 @@ router.get("/:id/transcript", async (req, res) => {
|
||||
}
|
||||
if (!renders(entry)) continue;
|
||||
|
||||
if (!foundStart) {
|
||||
if (lineNum <= afterLine) continue;
|
||||
foundStart = true;
|
||||
}
|
||||
|
||||
const message = isCodex ? codexMessage(entry, lineNum) : parseMessage(entry, lineNum);
|
||||
if (!message) continue;
|
||||
total++;
|
||||
|
||||
Reference in New Issue
Block a user