revert: re-apply EIP_CIRCUIT_BREAKER compound rendering
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m2s
CI / docker (push) Successful in 1m1s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 37s

Restores e8039f9. The compound rendering regression was caused by
the agent sending flat nodes without children, not the renderer code.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-29 18:22:43 +02:00
parent 673f0958c5
commit 59ddbb65b9
3 changed files with 149 additions and 3 deletions

View File

@@ -109,7 +109,7 @@ public class ElkDiagramRenderer implements DiagramRenderer {
NodeType.DO_TRY, NodeType.DO_CATCH, NodeType.DO_FINALLY,
NodeType.EIP_LOOP, NodeType.EIP_MULTICAST,
NodeType.EIP_AGGREGATE, NodeType.ON_EXCEPTION, NodeType.ERROR_HANDLER,
NodeType.ON_COMPLETION
NodeType.ON_COMPLETION, NodeType.EIP_CIRCUIT_BREAKER
);
/** Top-level handler types laid out in their own separate ELK graph. */
@@ -621,6 +621,84 @@ public class ElkDiagramRenderer implements DiagramRenderer {
sectionOrder.add(handler.getId());
}
ctx.doTrySectionOrder.put(rn.getId(), sectionOrder);
} else if (isCompound && rn.getType() == NodeType.EIP_CIRCUIT_BREAKER) {
// CIRCUIT_BREAKER: vertical container with _CB_MAIN for main path
// and onFallback as a compound section below (like DO_TRY pattern)
ctx.compoundNodeIds.add(rn.getId());
elkNode.setWidth(200);
elkNode.setHeight(100);
elkNode.setProperty(CoreOptions.ALGORITHM, "org.eclipse.elk.layered");
elkNode.setProperty(CoreOptions.DIRECTION, Direction.DOWN);
elkNode.setProperty(CoreOptions.SPACING_NODE_NODE, NODE_SPACING * 0.4);
elkNode.setProperty(CoreOptions.SPACING_EDGE_NODE, EDGE_SPACING * 0.3);
elkNode.setProperty(CoreOptions.PADDING,
new org.eclipse.elk.core.math.ElkPadding(COMPOUND_TOP_PADDING,
COMPOUND_SIDE_PADDING, COMPOUND_SIDE_PADDING, COMPOUND_SIDE_PADDING));
// Separate main path children from onFallback child
List<RouteNode> mainChildren = new ArrayList<>();
RouteNode fallbackNode = null;
for (RouteNode child : rn.getChildren()) {
if ("onFallback".equals(child.getLabel())) {
fallbackNode = child;
} else {
mainChildren.add(child);
}
}
List<String> sectionOrder = new ArrayList<>();
// Virtual _CB_MAIN wrapper for main path (horizontal flow)
if (!mainChildren.isEmpty()) {
String wrapperId = rn.getId() + "._cb_main";
ElkNode wrapper = ctx.factory.createElkNode();
wrapper.setIdentifier(wrapperId);
wrapper.setParent(elkNode);
wrapper.setWidth(200);
wrapper.setHeight(40);
wrapper.setProperty(CoreOptions.ALGORITHM, "org.eclipse.elk.layered");
wrapper.setProperty(CoreOptions.DIRECTION, Direction.RIGHT);
wrapper.setProperty(CoreOptions.SPACING_NODE_NODE, NODE_SPACING * 0.5);
wrapper.setProperty(CoreOptions.SPACING_EDGE_NODE, EDGE_SPACING * 0.5);
wrapper.setProperty(CoreOptions.PADDING,
new org.eclipse.elk.core.math.ElkPadding(8, 8, 8, 8));
ctx.compoundNodeIds.add(wrapperId);
ctx.elkNodeMap.put(wrapperId, wrapper);
sectionOrder.add(wrapperId);
for (RouteNode child : mainChildren) {
ctx.childNodeIds.add(child.getId());
createElkNodeRecursive(child, wrapper, ctx);
}
}
// onFallback as compound section containing its children
if (fallbackNode != null) {
ctx.childNodeIds.add(fallbackNode.getId());
ElkNode fallbackElk = ctx.factory.createElkNode();
fallbackElk.setIdentifier(fallbackNode.getId());
fallbackElk.setParent(elkNode);
fallbackElk.setWidth(200);
fallbackElk.setHeight(40);
fallbackElk.setProperty(CoreOptions.ALGORITHM, "org.eclipse.elk.layered");
fallbackElk.setProperty(CoreOptions.DIRECTION, Direction.RIGHT);
fallbackElk.setProperty(CoreOptions.SPACING_NODE_NODE, NODE_SPACING * 0.5);
fallbackElk.setProperty(CoreOptions.SPACING_EDGE_NODE, EDGE_SPACING * 0.5);
fallbackElk.setProperty(CoreOptions.PADDING,
new org.eclipse.elk.core.math.ElkPadding(18, 8, 8, 8));
ctx.compoundNodeIds.add(fallbackNode.getId());
ctx.elkNodeMap.put(fallbackNode.getId(), fallbackElk);
sectionOrder.add(fallbackNode.getId());
if (fallbackNode.getChildren() != null) {
for (RouteNode child : fallbackNode.getChildren()) {
ctx.childNodeIds.add(child.getId());
createElkNodeRecursive(child, fallbackElk, ctx);
}
}
}
ctx.doTrySectionOrder.put(rn.getId(), sectionOrder);
} else if (isCompound) {
ctx.compoundNodeIds.add(rn.getId());
@@ -690,6 +768,55 @@ public class ElkDiagramRenderer implements DiagramRenderer {
children.add(extractPositionedNode(handler, childElk, rootNode, ctx));
}
}
} else if (rn.getType() == NodeType.EIP_CIRCUIT_BREAKER) {
// CIRCUIT_BREAKER: extract _CB_MAIN wrapper, then onFallback section
String mainWrapperId = rn.getId() + "._cb_main";
ElkNode mainWrapperElk = ctx.elkNodeMap.get(mainWrapperId);
if (mainWrapperElk != null) {
List<PositionedNode> wrapperChildren = new ArrayList<>();
for (RouteNode child : rn.getChildren()) {
if (!"onFallback".equals(child.getLabel())) {
ElkNode childElk = ctx.elkNodeMap.get(child.getId());
if (childElk != null) {
wrapperChildren.add(extractPositionedNode(child, childElk, rootNode, ctx));
}
}
}
children.add(new PositionedNode(
mainWrapperId, "", "_CB_MAIN",
getAbsoluteX(mainWrapperElk, rootNode),
getAbsoluteY(mainWrapperElk, rootNode),
mainWrapperElk.getWidth(), mainWrapperElk.getHeight(),
wrapperChildren, null));
ctx.compoundInfos.put(mainWrapperId, new CompoundInfo(mainWrapperId, Color.WHITE));
}
// onFallback section with its children, type overridden to _CB_FALLBACK
for (RouteNode child : rn.getChildren()) {
if ("onFallback".equals(child.getLabel())) {
ElkNode childElk = ctx.elkNodeMap.get(child.getId());
if (childElk != null) {
List<PositionedNode> fallbackChildren = new ArrayList<>();
if (child.getChildren() != null) {
for (RouteNode fc : child.getChildren()) {
ElkNode fcElk = ctx.elkNodeMap.get(fc.getId());
if (fcElk != null) {
fallbackChildren.add(extractPositionedNode(fc, fcElk, rootNode, ctx));
}
}
}
children.add(new PositionedNode(
child.getId(),
child.getLabel() != null ? child.getLabel() : "",
"_CB_FALLBACK",
getAbsoluteX(childElk, rootNode),
getAbsoluteY(childElk, rootNode),
childElk.getWidth(), childElk.getHeight(),
fallbackChildren, null));
ctx.compoundInfos.put(child.getId(),
new CompoundInfo(child.getId(), colorForType(rn.getType())));
}
}
}
} else {
for (RouteNode child : rn.getChildren()) {
ElkNode childElk = ctx.elkNodeMap.get(child.getId());