add InsinTelemetryDiscoveredPrintersReceiver decorator
This commit is contained in:
@@ -0,0 +1,104 @@
|
|||||||
|
using EpsonPrintService;
|
||||||
|
using Inspectron.Epson;
|
||||||
|
using Inspectron.Epson.PrintServer.Telemetry;
|
||||||
|
|
||||||
|
namespace Inspectron.Epson.Tests.Telemetry;
|
||||||
|
|
||||||
|
public class InsinTelemetryDiscoveredPrintersReceiverTests
|
||||||
|
{
|
||||||
|
private sealed class RecordingTelemetry : IInsinTelemetry
|
||||||
|
{
|
||||||
|
public List<(string Kind, string Message)> Events { get; } = new();
|
||||||
|
public void Emit(string kind, string message) => Events.Add((kind, message));
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class CountingInner : IDiscoveredPrintersReceiver
|
||||||
|
{
|
||||||
|
public int Calls;
|
||||||
|
public Task OnPrintersDiscoveredAsync(IReadOnlyList<DiscoveredPrinter> printers)
|
||||||
|
{
|
||||||
|
Calls++;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DiscoveredPrinter Printer(string ip, string model = "TM-T30III") =>
|
||||||
|
new() { IPAddress = ip, ModelName = model };
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task First_sighting_emits_discovered_and_online()
|
||||||
|
{
|
||||||
|
var telemetry = new RecordingTelemetry();
|
||||||
|
var inner = new CountingInner();
|
||||||
|
var sut = new InsinTelemetryDiscoveredPrintersReceiver(inner, telemetry);
|
||||||
|
|
||||||
|
await sut.OnPrintersDiscoveredAsync(new[] { Printer("192.168.1.10") });
|
||||||
|
|
||||||
|
Assert.Equal(1, inner.Calls);
|
||||||
|
Assert.Collection(telemetry.Events,
|
||||||
|
e => Assert.Equal("printer.discovered", e.Kind),
|
||||||
|
e => Assert.Equal("printer.online", e.Kind));
|
||||||
|
Assert.Contains("printer=192.168.1.10", telemetry.Events[0].Message);
|
||||||
|
Assert.Contains("model=TM-T30III", telemetry.Events[0].Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Repeat_sighting_emits_nothing()
|
||||||
|
{
|
||||||
|
var telemetry = new RecordingTelemetry();
|
||||||
|
var sut = new InsinTelemetryDiscoveredPrintersReceiver(new CountingInner(), telemetry);
|
||||||
|
await sut.OnPrintersDiscoveredAsync(new[] { Printer("192.168.1.10") });
|
||||||
|
telemetry.Events.Clear();
|
||||||
|
|
||||||
|
await sut.OnPrintersDiscoveredAsync(new[] { Printer("192.168.1.10") });
|
||||||
|
|
||||||
|
Assert.Empty(telemetry.Events);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Disappearance_emits_offline()
|
||||||
|
{
|
||||||
|
var telemetry = new RecordingTelemetry();
|
||||||
|
var sut = new InsinTelemetryDiscoveredPrintersReceiver(new CountingInner(), telemetry);
|
||||||
|
await sut.OnPrintersDiscoveredAsync(new[] { Printer("192.168.1.10") });
|
||||||
|
telemetry.Events.Clear();
|
||||||
|
|
||||||
|
await sut.OnPrintersDiscoveredAsync(Array.Empty<DiscoveredPrinter>());
|
||||||
|
|
||||||
|
Assert.Single(telemetry.Events);
|
||||||
|
Assert.Equal("printer.offline", telemetry.Events[0].Kind);
|
||||||
|
Assert.Equal("printer=192.168.1.10", telemetry.Events[0].Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Reappearance_emits_online_only_not_discovered()
|
||||||
|
{
|
||||||
|
var telemetry = new RecordingTelemetry();
|
||||||
|
var sut = new InsinTelemetryDiscoveredPrintersReceiver(new CountingInner(), telemetry);
|
||||||
|
await sut.OnPrintersDiscoveredAsync(new[] { Printer("192.168.1.10") });
|
||||||
|
await sut.OnPrintersDiscoveredAsync(Array.Empty<DiscoveredPrinter>());
|
||||||
|
telemetry.Events.Clear();
|
||||||
|
|
||||||
|
await sut.OnPrintersDiscoveredAsync(new[] { Printer("192.168.1.10") });
|
||||||
|
|
||||||
|
Assert.Single(telemetry.Events);
|
||||||
|
Assert.Equal("printer.online", telemetry.Events[0].Kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Telemetry_failures_do_not_break_inner()
|
||||||
|
{
|
||||||
|
var telemetry = new ThrowingTelemetry();
|
||||||
|
var inner = new CountingInner();
|
||||||
|
var sut = new InsinTelemetryDiscoveredPrintersReceiver(inner, telemetry);
|
||||||
|
|
||||||
|
await sut.OnPrintersDiscoveredAsync(new[] { Printer("192.168.1.10") });
|
||||||
|
|
||||||
|
Assert.Equal(1, inner.Calls);
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class ThrowingTelemetry : IInsinTelemetry
|
||||||
|
{
|
||||||
|
public void Emit(string kind, string message) => throw new InvalidOperationException("boom");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
using Inspectron.Epson;
|
||||||
|
using Inspectron.Epson.PrintServer.Telemetry;
|
||||||
|
|
||||||
|
namespace EpsonPrintService;
|
||||||
|
|
||||||
|
public sealed class InsinTelemetryDiscoveredPrintersReceiver : IDiscoveredPrintersReceiver
|
||||||
|
{
|
||||||
|
private readonly IDiscoveredPrintersReceiver _inner;
|
||||||
|
private readonly IInsinTelemetry _telemetry;
|
||||||
|
private readonly HashSet<string> _seenIps = new();
|
||||||
|
private readonly Dictionary<string, bool> _present = new();
|
||||||
|
private readonly object _stateLock = new();
|
||||||
|
|
||||||
|
public InsinTelemetryDiscoveredPrintersReceiver(
|
||||||
|
IDiscoveredPrintersReceiver inner,
|
||||||
|
IInsinTelemetry telemetry)
|
||||||
|
{
|
||||||
|
_inner = inner;
|
||||||
|
_telemetry = telemetry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task OnPrintersDiscoveredAsync(IReadOnlyList<DiscoveredPrinter> printers)
|
||||||
|
{
|
||||||
|
await _inner.OnPrintersDiscoveredAsync(printers);
|
||||||
|
|
||||||
|
List<(string kind, string message)> toEmit;
|
||||||
|
lock (_stateLock)
|
||||||
|
{
|
||||||
|
toEmit = ComputeEvents(printers);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var (kind, message) in toEmit)
|
||||||
|
{
|
||||||
|
try { _telemetry.Emit(kind, message); }
|
||||||
|
catch { /* swallow: telemetry must never break discovery */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<(string, string)> ComputeEvents(IReadOnlyList<DiscoveredPrinter> printers)
|
||||||
|
{
|
||||||
|
var events = new List<(string, string)>();
|
||||||
|
var currentIps = new HashSet<string>();
|
||||||
|
foreach (var p in printers)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(p.IPAddress)) continue;
|
||||||
|
currentIps.Add(p.IPAddress);
|
||||||
|
|
||||||
|
if (_seenIps.Add(p.IPAddress))
|
||||||
|
events.Add((InsinEventKinds.PrinterDiscovered,
|
||||||
|
InsinMessageFormatter.Format(("printer", p.IPAddress), ("model", p.ModelName))));
|
||||||
|
|
||||||
|
if (!_present.TryGetValue(p.IPAddress, out var wasPresent) || !wasPresent)
|
||||||
|
events.Add((InsinEventKinds.PrinterOnline,
|
||||||
|
InsinMessageFormatter.Format(("printer", p.IPAddress))));
|
||||||
|
|
||||||
|
_present[p.IPAddress] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var kv in _present.ToList())
|
||||||
|
{
|
||||||
|
if (kv.Value && !currentIps.Contains(kv.Key))
|
||||||
|
{
|
||||||
|
events.Add((InsinEventKinds.PrinterOffline,
|
||||||
|
InsinMessageFormatter.Format(("printer", kv.Key))));
|
||||||
|
_present[kv.Key] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user