fix(console): bound the pending queue by lines and bytes
The console's pending, not-yet-drained queue was unbounded, so a hidden Console page that kept receiving verbose daemon-log chunks could grow without limit. - Pending lines are now bounded by both a line count and a byte budget. The oldest pending lines are dropped once either is exceeded, while the newest line is always kept so one huge line is never lost. - A formatted RPC result is ingested as one block under a single lock, so lines from other producers can never interleave inside it. The front-sequence accounting is also corrected: a pending line dropped by the cap never entered the visible buffer, so it no longer advances the front sequence. Only a front eviction or a clear does. Tests: the line and byte caps keep the newest lines, a single oversized line survives, a batch appends contiguously, and the front sequence advances only on a front eviction or clear. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2056,12 +2056,14 @@ void ConsoleTab::addFormattedResult(const std::string& result, bool is_error)
|
||||
|
||||
// Precompute JSON fold spans over the whole block so each opener line carries the offset
|
||||
// to its matching closer (the spans are relative, so they stay valid as the model's line
|
||||
// cap evicts from the front). This block is ingested atomically on the main thread.
|
||||
// cap evicts from the front). The block is ingested under one lock (ingestBatch).
|
||||
std::vector<std::string> texts;
|
||||
texts.reserve(resultLines.size());
|
||||
for (const auto& rl : resultLines) texts.push_back(rl.text);
|
||||
const std::vector<int> foldSpans = ComputeConsoleFoldSpans(texts);
|
||||
|
||||
std::vector<ConsoleModelLine> block;
|
||||
block.reserve(resultLines.size());
|
||||
for (std::size_t i = 0; i < resultLines.size(); ++i) {
|
||||
ConsoleChannel channel = ConsoleChannel::None;
|
||||
switch (resultLines[i].role) {
|
||||
@@ -2072,8 +2074,13 @@ void ConsoleTab::addFormattedResult(const std::string& result, bool is_error)
|
||||
case ConsoleResultLineRole::JsonBrace: channel = ConsoleChannel::JsonBrace; break;
|
||||
case ConsoleResultLineRole::Result: break;
|
||||
}
|
||||
model_.ingest(resultLines[i].text, channel, foldSpans[i]);
|
||||
ConsoleModelLine ml;
|
||||
ml.text = resultLines[i].text;
|
||||
ml.channel = channel;
|
||||
ml.foldSpan = foldSpans[i];
|
||||
block.push_back(std::move(ml));
|
||||
}
|
||||
model_.ingestBatch(std::move(block));
|
||||
}
|
||||
|
||||
void ConsoleTab::renderStatusHeader(ConsoleCommandExecutor& exec)
|
||||
|
||||
Reference in New Issue
Block a user