Forge
csharpdeeb25a2
1using System.Text;
2
3namespace CascadeIDE.Services;
4
5/// <summary>
6/// Accumulates text output while keeping only the last N characters.
7/// Helps avoid OOM when external tools produce huge logs.
8/// </summary>
9internal sealed class OutputAccumulator
10{
11 private readonly object _gate = new();
12 private readonly int _maxChars;
13 private readonly Queue<string> _chunks = new();
14 private int _totalChars;
15 private bool _truncated;
16
17 public OutputAccumulator(int maxChars)
18 {
19 _maxChars = Math.Max(1_024, maxChars);
20 }
21
22 public void Append(ReadOnlySpan<char> span)
23 {
24 if (span.IsEmpty)
25 return;
26
27 lock (_gate)
28 {
29 if (span.Length >= _maxChars)
30 {
31 _chunks.Clear();
32 _totalChars = 0;
33 _chunks.Enqueue(new string(span[^_maxChars..]));
34 _totalChars = _maxChars;
35 _truncated = true;
36 return;
37 }
38
39 _chunks.Enqueue(new string(span));
40 _totalChars += span.Length;
41
42 while (_totalChars > _maxChars && _chunks.Count > 0)
43 {
44 var removed = _chunks.Dequeue();
45 _totalChars -= removed.Length;
46 _truncated = true;
47 }
48 }
49 }
50
51 public string ToStringAndTrim()
52 {
53 lock (_gate)
54 {
55 if (_chunks.Count == 0)
56 return "";
57
58 var sb = new StringBuilder(_totalChars + (_truncated ? 32 : 0));
59 if (_truncated)
60 sb.Append("…(truncated)\r\n");
61
62 foreach (var c in _chunks)
63 sb.Append(c);
64
65 return sb.ToString().Trim();
66 }
67 }
68}
69
70
View only · write via MCP/CIDE