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 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) => {
|
const addAdj = (s: string, t: string) => {
|
||||||
if (!adjacency.has(s)) adjacency.set(s, []);
|
if (!adjacency.has(s)) adjacency.set(s, []);
|
||||||
adjacency.get(s)!.push(t);
|
adjacency.get(s)!.push(t);
|
||||||
@@ -136,31 +142,46 @@ export async function buildDependencyGraph(
|
|||||||
|
|
||||||
for (const p of processes) {
|
for (const p of processes) {
|
||||||
for (const pa of p.processAssets) {
|
for (const pa of p.processAssets) {
|
||||||
const s = pid(p.id);
|
const proc = pid(p.id);
|
||||||
const t = aid(pa.assetId);
|
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({
|
edges.push({
|
||||||
id: `${s}->${t}`,
|
id: `${proc}->${asset}`,
|
||||||
source: s,
|
source: proc,
|
||||||
target: t,
|
target: asset,
|
||||||
label: pa.role === "PRIMARY" ? "erzeugt" : "nutzt",
|
label: "erzeugt",
|
||||||
critical: isCritEdge(s, t),
|
critical: isCritEdge(proc, asset),
|
||||||
});
|
});
|
||||||
addAdj(s, t);
|
} 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));
|
const assetIds = new Set(assets.map((a) => a.id));
|
||||||
for (const r of relations) {
|
for (const r of relations) {
|
||||||
if (!assetIds.has(r.assetId) || !assetIds.has(r.relatedAssetId)) continue;
|
if (!assetIds.has(r.assetId) || !assetIds.has(r.relatedAssetId)) continue;
|
||||||
const s = aid(r.assetId);
|
// Analyse: asset hängt von relatedAsset ab
|
||||||
const t = aid(r.relatedAssetId);
|
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({
|
edges.push({
|
||||||
id: `${s}->${t}`,
|
id: `${s}->${t}`,
|
||||||
source: s,
|
source: s,
|
||||||
target: t,
|
target: t,
|
||||||
label: r.type === "depends_on" ? "hängt ab" : r.type,
|
label: "unterstützt",
|
||||||
critical: isCritEdge(s, t),
|
critical: isCritEdge(s, t),
|
||||||
});
|
});
|
||||||
addAdj(s, t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transitive Abhängigkeiten je kritischem Prozess → SPOF-Zählung je Asset
|
// 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);
|
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[]>();
|
const critAdj = new Map<string, string[]>();
|
||||||
for (const e of edges) {
|
for (const [s, targets] of adjacency) {
|
||||||
if (!e.critical) continue;
|
if ((critOf.get(s) ?? 1) < threshold) continue;
|
||||||
if (!critAdj.has(e.source)) critAdj.set(e.source, []);
|
const critTargets = targets.filter((t) => (critOf.get(t) ?? 1) >= threshold);
|
||||||
critAdj.get(e.source)!.push(e.target);
|
if (critTargets.length) critAdj.set(s, critTargets);
|
||||||
}
|
}
|
||||||
const nameOf = new Map(nodes.map((n) => [n.id, n.name]));
|
const nameOf = new Map(nodes.map((n) => [n.id, n.name]));
|
||||||
let longest: string[] = [];
|
let longest: string[] = [];
|
||||||
|
|||||||
Reference in New Issue
Block a user