d2 icon indicating copy to clipboard operation
d2 copied to clipboard

needs a way to enforce horizontal alignement of nodes

Open setop opened this issue 2 years ago • 9 comments

With

app -> db1: w
app -> db2: r

db1 and db2 are naturally aligned.

Screenshot 2023-03-01 at 14-12-42 D2 Playground

but if I want to explicit replication between my two DB

app -> db1: w
app -> db2: r
db1 -- db2

Then DBs are not aligned anymore making the diagram awkward.

Screenshot 2023-03-01 at 14-13-10 D2 Playground

Plantuml allows this by using different types of arrows : one dash means horizontal spacing, two dashes (and more) meand vertical spacing.

reminds me #724

setop avatar Mar 01 '23 13:03 setop

this is a limitation of dagre's layout. Here's a version in tala: https://play.d2lang.com/?script=RNExDsMgDEbh3ad4UmcqqDp56F1KoW0WjBAS14-cIRk_603-z_GUYquJvHsnvCg5KevSQxlSciIEl8iNr43P1n6eMo1cscb8V_y73t6ndeUZ4wG_KlH2AAAA__8%3D&layout=tala&

Screen Shot 2023-03-01 at 11 57 50 AM

gavin-ts avatar Mar 01 '23 19:03 gavin-ts

wait but plantuml was able to do that. i wonder how. @setop can you link or copy paste the plantuml script?

alixander avatar Mar 01 '23 20:03 alixander

@startuml
[app] --> [db1] : w
[app] --> [db2] : r
[db1] -> [db2]
@enduml

also online

setop avatar Mar 01 '23 23:03 setop

I also want to note that you can do this with Graphviz as well. Though the "usual" way is to use invisible node links, the much easier approach is to simply specify that an edge is not a constraint. As a result, the link itself becomes "optional" and doesn't influence the direction of the node rendering.

I've been fiddling with the Diagrams Python library and they make this pretty easy:

from diagrams.onprem.compute import Server

with Diagram('3 Node Test', show=False, direction='LR'):

    node1 = Server("Primary")
    node2 = Server("Replica")
    node3 = Server("Replica")

    node3 << Edge(constraint='false') << node1
    node1 >> Edge(constraint='false') >> node2
    node2 >> node3

And this is the result:

3_node_test

Now, the symmetry here isn't great, but you do get direct control over horizontal and vertical this way. I used it here as well:

two_by_three_+_1

That time, the only "optional" link is the one between the PG nodes in AZ1 and AZ2. If you make it required, it staggers the two clusters instead of just drawing the line differently. So I've basically started using the rule of "If you want the nodes to follow the render direction, use a regular link. If not, disable the link constraint." Thus I can do this:

one_by_three

Where D2 does this:

1x3

D2 elk does render "correctly" if you leave out the link between node 1 and node 2, but that defeats the purpose of the diagram.

Unfortunately Graphviz and its derivatives have other problems that make it a giant PITA to work with. D2 is much simpler, and if it could offer more horizontal/vertical control, would be essentially perfect. It's also a lot "prettier" out of the box, which is always nice.

bonesmoses avatar Mar 28 '23 22:03 bonesmoses

D2 is much simpler, and if it could offer more horizontal/vertical control, would be essentially perfect

@bonesmoses ❤️

should be doable. will find some time to prioritize this

alixander avatar Mar 29 '23 00:03 alixander

D2 is much simpler, and if it could offer more horizontal/vertical control, would be essentially perfect.

My feeling too

setop avatar Apr 01 '23 17:04 setop

we did a proof of concept which worked but was hacky: https://github.com/terrastruct/d2/pull/1120

will continue investigating more robust solutions

alixander avatar Apr 01 '23 17:04 alixander

we did a proof of concept which worked but was hacky: #1120

Really hacky indeed :) But at least proves we can control the layout engine to produce expected output, great news.

The main cons to me is it leaks implementation : we need to make the edge "phantom" in the layout engine so we ask the user to put is as a property. "phantom" has no functional meaning to the user.

I guess Plantuml has it right encode type of edge in the language. I know it's a more profound change to d2 as it impact the parsing. But it might be the price to pay.

setop avatar Apr 09 '23 07:04 setop

what about a "constraints" block?

constraints: {
app -> app2: top-align
}

ebuildy avatar Aug 18 '24 06:08 ebuildy