mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-13 12:15:10 +00:00
Fix memory leaks in dashboard frontend when using Chromium-based browsers
(including web view on Windows) * Remove heartbeat (browsers no longer allow windows to be closed anyway) * Prevent parallel requests pertaining to the executions queue Both measures eliminate parallel requests (which, apparently, can lead to memory leaks in Chromium-based browsers; no such observations in Firefox). Fixes #1389
This commit is contained in:
1 parent
26e989dddd
commit
a4913e6760
2 files changed
+31
-40
No files matched your search
@@ -40,6 +40,8 @@ Status of the `main` branch. Changes prior to the next official version change w
|
||||
- Fix: `rename_symbol` for Vue files now correctly propagates edits to the TypeScript server, enabling cross-file renames in `.vue` files
|
||||
- Fix: Lean4 stale cache — empty document symbol responses (returned before `lake build` completes) are no longer persisted, preventing symbols from being permanently hidden #1356
|
||||
|
||||
Dashboard:
|
||||
- Fix: Memory leaks in frontend when using Chromium-based browsers/Windows webview #1389
|
||||
|
||||
# v1.1.2 (2026-04-14)
|
||||
|
||||
|
||||
@@ -489,27 +489,6 @@ class Dashboard {
|
||||
// start on overview page
|
||||
self.navigateToPage("overview");
|
||||
});
|
||||
// Initialize heartbeat interval
|
||||
setInterval(this.heartbeat.bind(this), 250);
|
||||
}
|
||||
|
||||
heartbeat() {
|
||||
let self = this;
|
||||
$.ajax({
|
||||
url: '/heartbeat',
|
||||
type: 'GET',
|
||||
success: function (response) {
|
||||
self.heartbeatFailureCount = 0;
|
||||
},
|
||||
error: function (xhr, status, error) {
|
||||
self.heartbeatFailureCount++;
|
||||
console.error('Heartbeat failure; count = ', self.heartbeatFailureCount);
|
||||
if (self.heartbeatFailureCount >= 1) {
|
||||
console.log('Server appears to be down, closing tab');
|
||||
window.close();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
toggleMenu() {
|
||||
@@ -539,7 +518,6 @@ class Dashboard {
|
||||
// Start appropriate polling for the page
|
||||
if (page === 'overview') {
|
||||
this.loadNews();
|
||||
this.loadConfigOverview();
|
||||
this.startConfigPolling();
|
||||
this.startExecutionsPolling();
|
||||
} else if (page === 'logs') {
|
||||
@@ -597,7 +575,8 @@ class Dashboard {
|
||||
} else {
|
||||
console.log('Config unchanged, skipping display update');
|
||||
}
|
||||
}, error: function (xhr, status, error) {
|
||||
},
|
||||
error: function (xhr, status, error) {
|
||||
console.error('Error loading config overview:', error);
|
||||
self.$configDisplay.html('<div class="error-message">Error loading configuration</div>');
|
||||
self.$basicStatsDisplay.html('<div class="error-message">Error loading stats</div>');
|
||||
@@ -605,24 +584,23 @@ class Dashboard {
|
||||
self.$availableToolsDisplay.html('<div class="error-message">Error loading tools</div>');
|
||||
self.$availableModesDisplay.html('<div class="error-message">Error loading modes</div>');
|
||||
self.$availableContextsDisplay.html('<div class="error-message">Error loading contexts</div>');
|
||||
}, complete: function () {
|
||||
},
|
||||
complete: function () {
|
||||
self.waitingForConfigPollingResult = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
startConfigPolling() {
|
||||
this.loadConfigOverview();
|
||||
this.configPollInterval = setInterval(this.loadConfigOverview.bind(this), 1000);
|
||||
}
|
||||
|
||||
startExecutionsPolling() {
|
||||
this.loadExecutions()
|
||||
// Poll every 1 second for executions (independent of config polling)
|
||||
// This ensures stuck executions can still be cancelled even if config polling is blocked
|
||||
this.loadExecutions()
|
||||
this.executionsPollInterval = setInterval(() => {
|
||||
this.loadQueuedExecutions();
|
||||
this.loadLastExecution();
|
||||
}, 1000);
|
||||
this.executionsPollInterval = setInterval(this.loadExecutions.bind(this), 1000);
|
||||
}
|
||||
|
||||
displayConfig(config) {
|
||||
@@ -903,26 +881,30 @@ class Dashboard {
|
||||
|
||||
// ===== Executions Methods =====
|
||||
|
||||
loadQueuedExecutions() {
|
||||
loadQueuedExecutions(onComplete) {
|
||||
let self = this;
|
||||
$.ajax({
|
||||
url: '/queued_task_executions', type: 'GET', success: function (response) {
|
||||
url: '/queued_task_executions', type: 'GET',
|
||||
success: function (response) {
|
||||
if (response.status === 'success') {
|
||||
self.displayActiveExecutionsQueue(response.queued_executions || []);
|
||||
} else {
|
||||
console.error('Error loading executions:', response.message);
|
||||
}
|
||||
}, error: function (xhr, status, error) {
|
||||
},
|
||||
error: function (xhr, status, error) {
|
||||
console.error('Error loading executions:', error);
|
||||
self.$activeExecutionQueueDisplay.html('<div class="error-message">Error loading executions</div>');
|
||||
}
|
||||
},
|
||||
complete: onComplete
|
||||
});
|
||||
}
|
||||
|
||||
loadLastExecution() {
|
||||
loadLastExecution(onComplete) {
|
||||
let self = this;
|
||||
$.ajax({
|
||||
url: '/last_execution', type: 'GET', success: function (response) {
|
||||
url: '/last_execution', type: 'GET',
|
||||
success: function (response) {
|
||||
if (response.status === 'success') {
|
||||
if (response.last_execution !== null && response.last_execution.logged) {
|
||||
self.displayLastExecution(response.last_execution);
|
||||
@@ -930,21 +912,28 @@ class Dashboard {
|
||||
} else {
|
||||
console.error('Error loading last execution:', response.message);
|
||||
}
|
||||
}, error: function (xhr, status, error) {
|
||||
},
|
||||
error: function (xhr, status, error) {
|
||||
console.error('Error loading last execution:', error);
|
||||
self.$lastExecutionDisplay.html('<div class="error-message">Error loading last execution</div>');
|
||||
}
|
||||
},
|
||||
complete: onComplete
|
||||
});
|
||||
}
|
||||
|
||||
loadExecutions() {
|
||||
const self = this;
|
||||
if (this.waitingForExecutionsPollingResult) {
|
||||
console.log('Still waiting for previous executions poll result, skipping this poll');
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
this.waitingForExecutionsPollingResult = true;
|
||||
console.log('Polling for executions...');
|
||||
this.loadQueuedExecutions();
|
||||
this.loadLastExecution();
|
||||
this.loadQueuedExecutions(function() {
|
||||
self.loadLastExecution(function() {
|
||||
self.waitingForExecutionsPollingResult = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user