Refactor code structure for improved readability and maintainability; optimize performance in key functions.

This commit is contained in:
master
2025-12-22 19:06:31 +02:00
parent dfaa2079aa
commit 4602ccc3a3
1444 changed files with 109919 additions and 8058 deletions

View File

@@ -15,6 +15,8 @@ public sealed class InMemoryGraphRepository
new() { Id = "gn:acme:component:example", Kind = "component", Tenant = "acme", Attributes = new() { ["purl"] = "pkg:npm/example@1.0.0", ["ecosystem"] = "npm" } },
new() { Id = "gn:acme:component:widget", Kind = "component", Tenant = "acme", Attributes = new() { ["purl"] = "pkg:npm/widget@2.0.0", ["ecosystem"] = "npm" } },
new() { Id = "gn:acme:artifact:sha256:abc", Kind = "artifact", Tenant = "acme", Attributes = new() { ["digest"] = "sha256:abc", ["ecosystem"] = "container" } },
new() { Id = "gn:acme:sbom:sha256:sbom-a", Kind = "sbom", Tenant = "acme", Attributes = new() { ["sbom_digest"] = "sha256:sbom-a", ["artifact_digest"] = "sha256:abc", ["format"] = "cyclonedx" } },
new() { Id = "gn:acme:sbom:sha256:sbom-b", Kind = "sbom", Tenant = "acme", Attributes = new() { ["sbom_digest"] = "sha256:sbom-b", ["artifact_digest"] = "sha256:abc", ["format"] = "spdx" } },
new() { Id = "gn:acme:component:gamma", Kind = "component", Tenant = "acme", Attributes = new() { ["purl"] = "pkg:nuget/Gamma@3.1.4", ["ecosystem"] = "nuget" } },
new() { Id = "gn:bravo:component:widget", Kind = "component", Tenant = "bravo",Attributes = new() { ["purl"] = "pkg:npm/widget@2.0.0", ["ecosystem"] = "npm" } },
new() { Id = "gn:bravo:artifact:sha256:def", Kind = "artifact", Tenant = "bravo",Attributes = new() { ["digest"] = "sha256:def", ["ecosystem"] = "container" } },
@@ -24,6 +26,8 @@ public sealed class InMemoryGraphRepository
{
new() { Id = "ge:acme:artifact->component", Kind = "builds", Tenant = "acme", Source = "gn:acme:artifact:sha256:abc", Target = "gn:acme:component:example", Attributes = new() { ["reason"] = "sbom" } },
new() { Id = "ge:acme:component->component", Kind = "depends_on", Tenant = "acme", Source = "gn:acme:component:example", Target = "gn:acme:component:widget", Attributes = new() { ["scope"] = "runtime" } },
new() { Id = "ge:acme:sbom->artifact", Kind = "SBOM_VERSION_OF", Tenant = "acme", Source = "gn:acme:sbom:sha256:sbom-b", Target = "gn:acme:artifact:sha256:abc", Attributes = new() { ["relationship"] = "version_of" } },
new() { Id = "ge:acme:sbom->sbom", Kind = "SBOM_LINEAGE_PARENT", Tenant = "acme", Source = "gn:acme:sbom:sha256:sbom-b", Target = "gn:acme:sbom:sha256:sbom-a", Attributes = new() { ["relationship"] = "parent" } },
new() { Id = "ge:bravo:artifact->component", Kind = "builds", Tenant = "bravo", Source = "gn:bravo:artifact:sha256:def", Target = "gn:bravo:component:widget", Attributes = new() { ["reason"] = "sbom" } },
};
@@ -74,6 +78,114 @@ public sealed class InMemoryGraphRepository
return (nodes, edges);
}
public (IReadOnlyList<NodeTile> Nodes, IReadOnlyList<EdgeTile> Edges) GetLineage(string tenant, GraphLineageRequest request)
{
ArgumentNullException.ThrowIfNull(request);
var maxDepth = request.MaxDepth ?? 3;
if (maxDepth < 1)
{
maxDepth = 1;
}
var allowedKinds = BuildLineageKindFilter(request.RelationshipKinds);
var tenantNodes = _nodes
.Where(n => n.Tenant.Equals(tenant, StringComparison.Ordinal))
.ToList();
if (tenantNodes.Count == 0)
{
return (Array.Empty<NodeTile>(), Array.Empty<EdgeTile>());
}
var nodeById = tenantNodes.ToDictionary(n => n.Id, StringComparer.Ordinal);
var seedIds = new HashSet<string>(StringComparer.Ordinal);
if (!string.IsNullOrWhiteSpace(request.ArtifactDigest))
{
var digest = request.ArtifactDigest.Trim();
foreach (var node in tenantNodes.Where(n => HasAttribute(n, "artifact_digest", digest)))
{
seedIds.Add(node.Id);
}
}
if (!string.IsNullOrWhiteSpace(request.SbomDigest))
{
var digest = request.SbomDigest.Trim();
foreach (var node in tenantNodes.Where(n => HasAttribute(n, "sbom_digest", digest)))
{
seedIds.Add(node.Id);
}
}
if (seedIds.Count == 0)
{
return (Array.Empty<NodeTile>(), Array.Empty<EdgeTile>());
}
var tenantEdges = _edges
.Where(e => e.Tenant.Equals(tenant, StringComparison.Ordinal))
.Where(e => IsLineageEdgeAllowed(e, allowedKinds))
.ToList();
var adjacency = new Dictionary<string, List<EdgeTile>>(StringComparer.Ordinal);
foreach (var edge in tenantEdges)
{
AddAdjacency(adjacency, edge.Source, edge);
AddAdjacency(adjacency, edge.Target, edge);
}
var visitedNodes = new HashSet<string>(seedIds, StringComparer.Ordinal);
var visitedEdges = new HashSet<string>(StringComparer.Ordinal);
var frontier = new HashSet<string>(seedIds, StringComparer.Ordinal);
for (var depth = 0; depth < maxDepth && frontier.Count > 0; depth++)
{
var next = new HashSet<string>(StringComparer.Ordinal);
foreach (var nodeId in frontier)
{
if (!adjacency.TryGetValue(nodeId, out var edges))
{
continue;
}
foreach (var edge in edges)
{
if (visitedEdges.Add(edge.Id))
{
var other = string.Equals(edge.Source, nodeId, StringComparison.Ordinal)
? edge.Target
: edge.Source;
if (visitedNodes.Add(other))
{
next.Add(other);
}
}
}
}
frontier = next;
}
var resultNodes = new List<NodeTile>();
foreach (var nodeId in visitedNodes.OrderBy(id => id, StringComparer.Ordinal))
{
if (nodeById.TryGetValue(nodeId, out var node))
{
resultNodes.Add(node);
}
}
var resultEdges = tenantEdges
.Where(edge => visitedEdges.Contains(edge.Id))
.Where(edge => visitedNodes.Contains(edge.Source) && visitedNodes.Contains(edge.Target))
.OrderBy(edge => edge.Id, StringComparer.Ordinal)
.ToList();
return (resultNodes, resultEdges);
}
public (IReadOnlyList<NodeTile> Nodes, IReadOnlyList<EdgeTile> Edges)? GetSnapshot(string tenant, string snapshotId)
{
if (_snapshots.TryGetValue($"{tenant}:{snapshotId}", out var snap))
@@ -128,6 +240,69 @@ public sealed class InMemoryGraphRepository
return dict;
}
private static bool HasAttribute(NodeTile node, string key, string expected)
{
if (!node.Attributes.TryGetValue(key, out var value) || value is null)
{
return false;
}
return string.Equals(value.ToString(), expected, StringComparison.OrdinalIgnoreCase);
}
private static HashSet<string> BuildLineageKindFilter(string[]? relationshipKinds)
{
if (relationshipKinds is null || relationshipKinds.Length == 0)
{
return new HashSet<string>(StringComparer.OrdinalIgnoreCase);
}
var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var value in relationshipKinds)
{
if (string.IsNullOrWhiteSpace(value))
{
continue;
}
set.Add(value.Trim());
}
return set;
}
private static bool IsLineageEdgeAllowed(EdgeTile edge, HashSet<string> allowedKinds)
{
if (allowedKinds.Count == 0)
{
return edge.Kind.StartsWith("SBOM_LINEAGE_", StringComparison.OrdinalIgnoreCase)
|| string.Equals(edge.Kind, "SBOM_VERSION_OF", StringComparison.OrdinalIgnoreCase);
}
if (allowedKinds.Contains(edge.Kind))
{
return true;
}
if (edge.Attributes.TryGetValue("relationship", out var relationship) && relationship is not null)
{
return allowedKinds.Contains(relationship.ToString() ?? string.Empty);
}
return false;
}
private static void AddAdjacency(Dictionary<string, List<EdgeTile>> adjacency, string nodeId, EdgeTile edge)
{
if (!adjacency.TryGetValue(nodeId, out var list))
{
list = new List<EdgeTile>();
adjacency[nodeId] = list;
}
list.Add(edge);
}
private static bool MatchesQuery(NodeTile node, string query)
{
var q = query.ToLowerInvariant();