Abhängigkeitsgraph: klarere Anordnung (Abhängigkeiten links, Prozess
Mitte, erzeugte Assets rechts) - Anzeige-Kanten rollenabhängig orientiert: primäre/erzeugte Assets rechts vom Prozess, unterstützende Abhängigkeiten links (Pfeile fließen sauber links→rechts, Label "erzeugt" bzw. "unterstützt") - Analyse-Adjazenz (SPOF, kritischer Pfad, transitive Abhängigkeiten) von der Anzeige entkoppelt und über alle Asset-Bezüge berechnet Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
d9685b65b9
commit
18bd82e54a
@@ -124,9 +124,15 @@ export async function buildDependencyGraph(
|
||||
});
|
||||
}
|
||||
|
||||
// Kanten: Prozess → Asset (Rolle), Asset → Asset (Relation)
|
||||
// Zwei Sichten:
|
||||
// - adjacency (Analyse): Abhängigkeitsrichtung (Abhängiger → Abhängigkeit),
|
||||
// Basis für kritischen Pfad, SPOF, transitive Abhängigkeiten.
|
||||
// - edges (Anzeige): links = unterstützende Abhängigkeit, Mitte = Prozess,
|
||||
// rechts = erzeugtes primäres Asset. Pfeile fließen sauber von links nach
|
||||
// rechts, daher zeigen unterstützende Kanten VON der Abhängigkeit zum
|
||||
// Nutzer/Prozess.
|
||||
const edges: GraphEdge[] = [];
|
||||
const adjacency = new Map<string, string[]>(); // gerichtete Abhängigkeit source→target
|
||||
const adjacency = new Map<string, string[]>();
|
||||
const addAdj = (s: string, t: string) => {
|
||||
if (!adjacency.has(s)) adjacency.set(s, []);
|
||||
adjacency.get(s)!.push(t);
|
||||
@@ -136,31 +142,46 @@ export async function buildDependencyGraph(
|
||||
|
||||
for (const p of processes) {
|
||||
for (const pa of p.processAssets) {
|
||||
const s = pid(p.id);
|
||||
const t = aid(pa.assetId);
|
||||
edges.push({
|
||||
id: `${s}->${t}`,
|
||||
source: s,
|
||||
target: t,
|
||||
label: pa.role === "PRIMARY" ? "erzeugt" : "nutzt",
|
||||
critical: isCritEdge(s, t),
|
||||
});
|
||||
addAdj(s, t);
|
||||
const proc = pid(p.id);
|
||||
const asset = aid(pa.assetId);
|
||||
// Analyse: Prozess ist auf alle zugeordneten Assets angewiesen (SPOF/Pfad)
|
||||
addAdj(proc, asset);
|
||||
if (pa.role === "PRIMARY") {
|
||||
// erzeugtes Asset rechts vom Prozess
|
||||
edges.push({
|
||||
id: `${proc}->${asset}`,
|
||||
source: proc,
|
||||
target: asset,
|
||||
label: "erzeugt",
|
||||
critical: isCritEdge(proc, asset),
|
||||
});
|
||||
} else {
|
||||
// unterstützendes Asset links vom Prozess (Kante zeigt zum Prozess)
|
||||
edges.push({
|
||||
id: `${asset}->${proc}`,
|
||||
source: asset,
|
||||
target: proc,
|
||||
label: "unterstützt",
|
||||
critical: isCritEdge(asset, proc),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
const assetIds = new Set(assets.map((a) => a.id));
|
||||
for (const r of relations) {
|
||||
if (!assetIds.has(r.assetId) || !assetIds.has(r.relatedAssetId)) continue;
|
||||
const s = aid(r.assetId);
|
||||
const t = aid(r.relatedAssetId);
|
||||
// Analyse: asset hängt von relatedAsset ab
|
||||
addAdj(aid(r.assetId), aid(r.relatedAssetId));
|
||||
// Anzeige: Abhängigkeit (relatedAsset) links, Nutzer (asset) rechts
|
||||
const s = aid(r.relatedAssetId);
|
||||
const t = aid(r.assetId);
|
||||
edges.push({
|
||||
id: `${s}->${t}`,
|
||||
source: s,
|
||||
target: t,
|
||||
label: r.type === "depends_on" ? "hängt ab" : r.type,
|
||||
label: "unterstützt",
|
||||
critical: isCritEdge(s, t),
|
||||
});
|
||||
addAdj(s, t);
|
||||
}
|
||||
|
||||
// Transitive Abhängigkeiten je kritischem Prozess → SPOF-Zählung je Asset
|
||||
@@ -191,12 +212,13 @@ export async function buildDependencyGraph(
|
||||
}
|
||||
spofs.sort((a, b) => b.count - a.count);
|
||||
|
||||
// Längster kritischer Pfad (DFS über kritische Kanten ab kritischen Prozessen)
|
||||
// Längster kritischer Pfad (Abhängigkeitskette): DFS über die Analyse-Adjazenz,
|
||||
// beschränkt auf kritische Knoten, ab kritischen Prozessen.
|
||||
const critAdj = new Map<string, string[]>();
|
||||
for (const e of edges) {
|
||||
if (!e.critical) continue;
|
||||
if (!critAdj.has(e.source)) critAdj.set(e.source, []);
|
||||
critAdj.get(e.source)!.push(e.target);
|
||||
for (const [s, targets] of adjacency) {
|
||||
if ((critOf.get(s) ?? 1) < threshold) continue;
|
||||
const critTargets = targets.filter((t) => (critOf.get(t) ?? 1) >= threshold);
|
||||
if (critTargets.length) critAdj.set(s, critTargets);
|
||||
}
|
||||
const nameOf = new Map(nodes.map((n) => [n.id, n.name]));
|
||||
let longest: string[] = [];
|
||||
|
||||
Reference in New Issue
Block a user