up
This commit is contained in:
@@ -8,14 +8,16 @@ namespace StellaOps.Graph.Api.Services;
|
||||
public sealed class InMemoryGraphDiffService : IGraphDiffService
|
||||
{
|
||||
private readonly InMemoryGraphRepository _repository;
|
||||
private readonly IGraphMetrics _metrics;
|
||||
private static readonly JsonSerializerOptions Options = new(JsonSerializerDefaults.Web)
|
||||
{
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
||||
};
|
||||
|
||||
public InMemoryGraphDiffService(InMemoryGraphRepository repository)
|
||||
public InMemoryGraphDiffService(InMemoryGraphRepository repository, IGraphMetrics metrics)
|
||||
{
|
||||
_repository = repository;
|
||||
_metrics = metrics;
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<string> DiffAsync(string tenant, GraphDiffRequest request, [EnumeratorCancellation] CancellationToken ct = default)
|
||||
@@ -26,6 +28,7 @@ public sealed class InMemoryGraphDiffService : IGraphDiffService
|
||||
var edgeBudgetRemaining = budget.Edges ?? 10000;
|
||||
var budgetRemaining = tileBudgetLimit;
|
||||
var seq = 0;
|
||||
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||||
|
||||
var snapA = _repository.GetSnapshot(tenant, request.SnapshotA);
|
||||
var snapB = _repository.GetSnapshot(tenant, request.SnapshotB);
|
||||
@@ -39,6 +42,8 @@ public sealed class InMemoryGraphDiffService : IGraphDiffService
|
||||
Details = new { request.SnapshotA, request.SnapshotB }
|
||||
};
|
||||
yield return JsonSerializer.Serialize(new TileEnvelope("error", seq++, error, Cost(tileBudgetLimit, budgetRemaining)), Options);
|
||||
stopwatch.Stop();
|
||||
_metrics.QueryLatencySeconds.Record(stopwatch.Elapsed.TotalSeconds, new KeyValuePair<string, object?>("route", "/graph/diff"));
|
||||
yield break;
|
||||
}
|
||||
|
||||
@@ -49,15 +54,15 @@ public sealed class InMemoryGraphDiffService : IGraphDiffService
|
||||
|
||||
foreach (var added in nodesB.Values.Where(n => !nodesA.ContainsKey(n.Id)).OrderBy(n => n.Id, StringComparer.Ordinal))
|
||||
{
|
||||
if (!Spend(ref budgetRemaining, ref nodeBudgetRemaining, tileBudgetLimit, seq, out var tile)) { yield return tile!; yield break; }
|
||||
yield return JsonSerializer.Serialize(new TileEnvelope("node_added", seq++, added, Cost(tileBudgetLimit, budgetRemaining)), Options);
|
||||
}
|
||||
if (!Spend(ref budgetRemaining, ref nodeBudgetRemaining, tileBudgetLimit, seq, out var tile)) { _metrics.BudgetDenied.Add(1, new KeyValuePair<string, object?>("reason", "nodes")); yield return tile!; yield break; }
|
||||
yield return JsonSerializer.Serialize(new TileEnvelope("node_added", seq++, added, Cost(tileBudgetLimit, budgetRemaining)), Options);
|
||||
}
|
||||
|
||||
foreach (var removed in nodesA.Values.Where(n => !nodesB.ContainsKey(n.Id)).OrderBy(n => n.Id, StringComparer.Ordinal))
|
||||
{
|
||||
if (!Spend(ref budgetRemaining, ref nodeBudgetRemaining, tileBudgetLimit, seq, out var tile)) { yield return tile!; yield break; }
|
||||
yield return JsonSerializer.Serialize(new TileEnvelope("node_removed", seq++, removed, Cost(tileBudgetLimit, budgetRemaining)), Options);
|
||||
}
|
||||
if (!Spend(ref budgetRemaining, ref nodeBudgetRemaining, tileBudgetLimit, seq, out var tile)) { _metrics.BudgetDenied.Add(1, new KeyValuePair<string, object?>("reason", "nodes")); yield return tile!; yield break; }
|
||||
yield return JsonSerializer.Serialize(new TileEnvelope("node_removed", seq++, removed, Cost(tileBudgetLimit, budgetRemaining)), Options);
|
||||
}
|
||||
|
||||
foreach (var common in nodesA.Keys.Intersect(nodesB.Keys, StringComparer.Ordinal).OrderBy(k => k, StringComparer.Ordinal))
|
||||
{
|
||||
@@ -65,7 +70,7 @@ public sealed class InMemoryGraphDiffService : IGraphDiffService
|
||||
var b = nodesB[common];
|
||||
if (!AttributesEqual(a.Attributes, b.Attributes))
|
||||
{
|
||||
if (!Spend(ref budgetRemaining, ref nodeBudgetRemaining, tileBudgetLimit, seq, out var tile)) { yield return tile!; yield break; }
|
||||
if (!Spend(ref budgetRemaining, ref nodeBudgetRemaining, tileBudgetLimit, seq, out var tile)) { _metrics.BudgetDenied.Add(1, new KeyValuePair<string, object?>("reason", "nodes")); yield return tile!; yield break; }
|
||||
var diff = new DiffTile
|
||||
{
|
||||
EntityType = "node",
|
||||
@@ -82,13 +87,13 @@ public sealed class InMemoryGraphDiffService : IGraphDiffService
|
||||
{
|
||||
foreach (var added in edgesB.Values.Where(e => !edgesA.ContainsKey(e.Id)).OrderBy(e => e.Id, StringComparer.Ordinal))
|
||||
{
|
||||
if (!Spend(ref budgetRemaining, ref edgeBudgetRemaining, tileBudgetLimit, seq, out var tile)) { yield return tile!; yield break; }
|
||||
if (!Spend(ref budgetRemaining, ref edgeBudgetRemaining, tileBudgetLimit, seq, out var tile)) { _metrics.BudgetDenied.Add(1, new KeyValuePair<string, object?>("reason", "edges")); yield return tile!; yield break; }
|
||||
yield return JsonSerializer.Serialize(new TileEnvelope("edge_added", seq++, added, Cost(tileBudgetLimit, budgetRemaining)), Options);
|
||||
}
|
||||
|
||||
foreach (var removed in edgesA.Values.Where(e => !edgesB.ContainsKey(e.Id)).OrderBy(e => e.Id, StringComparer.Ordinal))
|
||||
{
|
||||
if (!Spend(ref budgetRemaining, ref edgeBudgetRemaining, tileBudgetLimit, seq, out var tile)) { yield return tile!; yield break; }
|
||||
if (!Spend(ref budgetRemaining, ref edgeBudgetRemaining, tileBudgetLimit, seq, out var tile)) { _metrics.BudgetDenied.Add(1, new KeyValuePair<string, object?>("reason", "edges")); yield return tile!; yield break; }
|
||||
yield return JsonSerializer.Serialize(new TileEnvelope("edge_removed", seq++, removed, Cost(tileBudgetLimit, budgetRemaining)), Options);
|
||||
}
|
||||
|
||||
@@ -98,12 +103,12 @@ public sealed class InMemoryGraphDiffService : IGraphDiffService
|
||||
var b = edgesB[common];
|
||||
if (!AttributesEqual(a.Attributes, b.Attributes))
|
||||
{
|
||||
if (!Spend(ref budgetRemaining, ref edgeBudgetRemaining, tileBudgetLimit, seq, out var tile)) { yield return tile!; yield break; }
|
||||
var diff = new DiffTile
|
||||
{
|
||||
EntityType = "edge",
|
||||
ChangeType = "changed",
|
||||
Id = common,
|
||||
if (!Spend(ref budgetRemaining, ref edgeBudgetRemaining, tileBudgetLimit, seq, out var tile)) { _metrics.BudgetDenied.Add(1, new KeyValuePair<string, object?>("reason", "edges")); yield return tile!; yield break; }
|
||||
var diff = new DiffTile
|
||||
{
|
||||
EntityType = "edge",
|
||||
ChangeType = "changed",
|
||||
Id = common,
|
||||
Before = a,
|
||||
After = b
|
||||
};
|
||||
@@ -126,6 +131,9 @@ public sealed class InMemoryGraphDiffService : IGraphDiffService
|
||||
yield return JsonSerializer.Serialize(new TileEnvelope("stats", seq++, stats, Cost(tileBudgetLimit, budgetRemaining)), Options);
|
||||
}
|
||||
|
||||
stopwatch.Stop();
|
||||
_metrics.QueryLatencySeconds.Record(stopwatch.Elapsed.TotalSeconds, new KeyValuePair<string, object?>("route", "/graph/diff"));
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user