Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

63 строки
2.5KB

  1. using System.Diagnostics;
  2. namespace EnvelopeRenderer.Cli.Progress;
  3. /// <summary>
  4. /// Writes PROGRESS lines to the given <see cref="TextWriter"/> (stdout in production). Only the
  5. /// high-frequency `render` event is throttled — to at least once per second, per the "Emit
  6. /// machine-readable progress during render" story — because `startup`, `complete`, and `failure`
  7. /// each happen exactly once per run and must never be dropped. The elapsed-time source is
  8. /// injected (rather than reading <see cref="Stopwatch"/> directly) so tests can drive throttling
  9. /// deterministically without real `Thread.Sleep` calls; <see cref="CreateDefault"/> wires up a
  10. /// real stopwatch for production use.
  11. /// </summary>
  12. public sealed class ConsoleProgressReporter : IProgressReporter
  13. {
  14. private readonly TextWriter _output;
  15. private readonly Func<long> _elapsedMillisecondsProvider;
  16. private readonly long _minIntervalMs;
  17. private long? _lastEmittedAtMs;
  18. public ConsoleProgressReporter(
  19. TextWriter output, Func<long> elapsedMillisecondsProvider, long minIntervalMs = 1000)
  20. {
  21. _output = output;
  22. _elapsedMillisecondsProvider = elapsedMillisecondsProvider;
  23. _minIntervalMs = minIntervalMs;
  24. }
  25. /// <summary>Production factory: throttles against a real, freshly-started stopwatch.</summary>
  26. public static ConsoleProgressReporter CreateDefault(TextWriter output)
  27. {
  28. var stopwatch = Stopwatch.StartNew();
  29. return new ConsoleProgressReporter(output, () => stopwatch.ElapsedMilliseconds);
  30. }
  31. public void Startup() => Write("startup", 0);
  32. public void ReportRenderProgress(int completed)
  33. {
  34. var elapsed = _elapsedMillisecondsProvider();
  35. // Always emit the first call immediately (so a slow run shows *something* right away),
  36. // then suppress further calls until at least _minIntervalMs has passed since the last
  37. // one actually written — this is the "at least once per second, not once per row" rule.
  38. if (_lastEmittedAtMs is not null && elapsed - _lastEmittedAtMs.Value < _minIntervalMs)
  39. {
  40. return;
  41. }
  42. _lastEmittedAtMs = elapsed;
  43. Write("render", completed);
  44. }
  45. public void Complete(int completed) => Write("complete", completed);
  46. public void Failure(int completed, string reason) => Write("failure", completed, reason);
  47. private void Write(string kind, int completed, string? reason = null)
  48. {
  49. _output.WriteLine(ProgressEventFormatter.Format(kind, _elapsedMillisecondsProvider(), completed, reason));
  50. }
  51. }

Powered by TurnKey Linux.