Fix memory leak: throttle streaming updates, remove console.logs
This commit is contained in:
+28
-26
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { useState, useEffect, useRef, useCallback } from "react";
|
||||
import { useParams, Link, useSearchParams } from "react-router-dom";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import { useAuth } from "../contexts/AuthContext";
|
||||
@@ -69,6 +69,26 @@ export default function GamePage() {
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const messagesContainerRef = useRef<HTMLDivElement>(null);
|
||||
const inputRef = useRef<HTMLTextAreaElement>(null);
|
||||
// Refs for throttled streaming updates
|
||||
const streamingBufferRef = useRef("");
|
||||
const lastUpdateRef = useRef(0);
|
||||
|
||||
// Throttled streaming update (every 50ms instead of every chunk)
|
||||
const updateStreamingContent = useCallback((chunk: string) => {
|
||||
streamingBufferRef.current += chunk;
|
||||
const now = Date.now();
|
||||
if (now - lastUpdateRef.current > 50) {
|
||||
setStreamingContent(streamingBufferRef.current);
|
||||
lastUpdateRef.current = now;
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Flush remaining content
|
||||
const flushStreamingContent = useCallback(() => {
|
||||
if (streamingBufferRef.current) {
|
||||
setStreamingContent(streamingBufferRef.current);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const loadGame = async () => {
|
||||
@@ -87,7 +107,6 @@ export default function GamePage() {
|
||||
|
||||
// Загружаем список сессий
|
||||
const sessions = await getSessionsList(id);
|
||||
console.log("[GamePage] Sessions list:", sessions);
|
||||
setSessionsList(sessions);
|
||||
|
||||
const characterId = searchParams.get("character");
|
||||
@@ -109,10 +128,8 @@ export default function GamePage() {
|
||||
// Если есть сессии, загружаем последнюю (или создаём новую)
|
||||
if (sessions.length > 0) {
|
||||
const latestSession = sessions[0];
|
||||
console.log("[GamePage] Loading latest session:", latestSession);
|
||||
setCurrentSessionId(latestSession.id);
|
||||
const sessionData = await getSession(id, latestSession.id);
|
||||
console.log("[GamePage] Session data loaded:", sessionData);
|
||||
if (sessionData) {
|
||||
setSession(sessionData);
|
||||
// Загружаем персонажа: приоритет URL > сессия
|
||||
@@ -170,7 +187,6 @@ export default function GamePage() {
|
||||
id: (updatedStory as any)._id || updatedStory.id,
|
||||
};
|
||||
setStory(normalizedStory);
|
||||
console.log("[GamePage] История обновлена после возврата на страницу");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -285,6 +301,7 @@ export default function GamePage() {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
setStreamingContent("");
|
||||
streamingBufferRef.current = "";
|
||||
|
||||
// Создаём AbortController для возможности отмены
|
||||
abortControllerRef.current = new AbortController();
|
||||
@@ -295,13 +312,12 @@ export default function GamePage() {
|
||||
story,
|
||||
session.messages,
|
||||
input.trim(),
|
||||
(chunk) => {
|
||||
setStreamingContent((prev) => prev + chunk);
|
||||
},
|
||||
updateStreamingContent,
|
||||
playerCharacter || undefined,
|
||||
session,
|
||||
abortControllerRef.current.signal,
|
||||
);
|
||||
flushStreamingContent();
|
||||
|
||||
const assistantMessage: ChatMessage = {
|
||||
id: generateId(),
|
||||
@@ -321,7 +337,6 @@ export default function GamePage() {
|
||||
// Генерируем сводку каждые 20 сообщений
|
||||
let newSummary = session.storySummary;
|
||||
if (allMessages.length % 20 === 0 && allMessages.length > 0) {
|
||||
console.log("[GamePage] Generating story summary...");
|
||||
newSummary = await generateStorySummary(
|
||||
story,
|
||||
allMessages,
|
||||
@@ -336,17 +351,11 @@ export default function GamePage() {
|
||||
storySummary: newSummary,
|
||||
};
|
||||
|
||||
const saved = await apiSaveSession(
|
||||
await apiSaveSession(
|
||||
story.id,
|
||||
currentSessionId,
|
||||
finalSession,
|
||||
);
|
||||
console.log(
|
||||
"[GamePage] Session saved:",
|
||||
saved,
|
||||
"Messages:",
|
||||
allMessages.length,
|
||||
);
|
||||
setSession(finalSession);
|
||||
} catch (err) {
|
||||
if (err instanceof Error && err.name === "AbortError") {
|
||||
@@ -466,6 +475,7 @@ export default function GamePage() {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
setStreamingContent("");
|
||||
streamingBufferRef.current = "";
|
||||
|
||||
abortControllerRef.current = new AbortController();
|
||||
|
||||
@@ -475,13 +485,12 @@ export default function GamePage() {
|
||||
story,
|
||||
messagesUpToEdit,
|
||||
editContent.trim(),
|
||||
(chunk) => {
|
||||
setStreamingContent((prev) => prev + chunk);
|
||||
},
|
||||
updateStreamingContent,
|
||||
playerCharacter || undefined,
|
||||
session,
|
||||
abortControllerRef.current.signal,
|
||||
);
|
||||
flushStreamingContent();
|
||||
|
||||
// Сохраняем ответ ИИ в текущую версию
|
||||
const finalVersions: MessageVersion[] = [...newVersions];
|
||||
@@ -653,12 +662,6 @@ export default function GamePage() {
|
||||
};
|
||||
|
||||
const handleSwitchSession = async (sessionId: string) => {
|
||||
console.log(
|
||||
"[GamePage] Switching to session:",
|
||||
sessionId,
|
||||
"current:",
|
||||
currentSessionId,
|
||||
);
|
||||
if (!id || sessionId === currentSessionId) {
|
||||
setShowSessionMenu(false);
|
||||
return;
|
||||
@@ -668,7 +671,6 @@ export default function GamePage() {
|
||||
setIsInitialLoading(true);
|
||||
|
||||
const sessionData = await getSession(id, sessionId);
|
||||
console.log("[GamePage] Loaded session data:", sessionData);
|
||||
if (sessionData) {
|
||||
setCurrentSessionId(sessionId);
|
||||
setSession(sessionData);
|
||||
|
||||
@@ -67,19 +67,6 @@ export async function sendMessage(
|
||||
}
|
||||
|
||||
const data: DeepSeekResponse = await response.json();
|
||||
|
||||
// Log cache usage (for debugging)
|
||||
if (data.usage) {
|
||||
console.log(
|
||||
`[DeepSeek] Tokens - Prompt: ${data.usage.prompt_tokens}, Completion: ${data.usage.completion_tokens}`,
|
||||
);
|
||||
if (data.usage.prompt_cache_hit_tokens !== undefined) {
|
||||
console.log(
|
||||
`[DeepSeek] Cache - Hit: ${data.usage.prompt_cache_hit_tokens}, Miss: ${data.usage.prompt_cache_miss_tokens}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return data.choices[0]?.message?.content || "";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user