digraph SMPAgent {
  graph [fontname=arial]
  node [fontname=arial fontsize=11 shape=box]
  edge [fontname=arial fontsize=10 arrowhead=open arrowtail=open]

  main [shape=hexagon color=orange label="main\nthread"]
  aSock [label="user agent TCP socket" color=darkgreen]

  subgraph clusterPersistence {
    graph [fontsize=11 color=gray]
    label="persistence (sqlite)"
    connectionsStore [shape=cylinder label="duplex connections,\nSMP queues,\nrecent messages"]
  }

  subgraph clusterAgent {
    graph [color=gray]
    node [shape=hexagon color=orange]
    label="agent threads" 
    connectClnt
    runClnt
  }

  main -> {runClnt connectClnt} [style=dashed label="race" color=orange fontcolor=orange]
  aSock -> connectClnt [color=darkgreen]

  subgraph clusterUserTCP {
    graph [color=gray]
    label="1 group per user TCP connection"
    uSock [label="user connection TCP socket" color=darkgreen]

    subgraph clusterUserTCPThreads {
      graph [fontsize=11 color=gray]
      label="user TCP threads"
      node [shape=hexagon, color=orange]
      uRcv [label="user\nreceive"]
      uSnd [label="user\nsend"]
    }

    uSock -> uRcv [color=darkgreen]
    uSnd -> uSock [color=darkgreen]
  }

  subgraph clusterUser {
    graph [color=gray]
    label="1 group per user TCP connection"

    subgraph clusterUserInterface {
      graph [fontsize=11]
      label="user queues"
      uInq [shape=rarrow label="user\nreceive\nTBQueue"]
      uOutq [shape=larrow label="user\nsend\nTBQueue"]
    }

    subgraph clusterUserThreads {
      graph [fontsize=11]
      label="user threads\nNote: `user agent` sends\nall commands to `commands TBQueue`s\n(invalid commands with attached responses),\nand only valid commands to `server TBQueue`.\nIt is used to respond in correct order."
      node [shape=hexagon, color=orange]
      uAgent [label="user\nagent"]
      uProcess [label="process\nresponses"]
    }

    uRcv -> uInq -> uAgent [color=darkgreen]
    uProcess -> uOutq -> uSnd [color=darkgreen]
    {uRcv uAgent} -> uOutq [color=green]

    uRespq [shape=rarrow label="user\nSMP\nTBQueue"]

    subgraph clusterClient {
      label="1 group per SMP client/server connection"
      runClient [shape=hexagon, color=orange]
      sOutq [shape=rarrow label="srv send\nTBQueue"]
      sSock [label="SMP client connection TCP socket" color=blue]

      subgraph clusterServerThreads {
        graph [fontsize=11]
        label="SMP client threads"
        node [shape=hexagon, color=orange]
        sAgent [label="server\nreceive"]
        sSnd [label="server\nsend"]
      }

      runClient -> {sAgent sSnd} [style=dashed label=race color=orange fontcolor=orange]
      {uAgent uProcess} -> sOutq -> sSnd -> sSock -> sAgent [color=blue]
    }

    userState [label="connected\nservers,\nsubscribed\nqueues,\nsent\ncommands\n(STM)" shape="folder"]

    {uAgent uProcess} -> userState [dir=both color="#FF8888"]
    {uAgent uProcess} -> connectionsStore [dir=both color="#880000"]

    connectClnt -> uSock [style=dashed label="connect" color=darkgreen fontcolor=darkgreen]
    connectClnt -> {uRcv uSnd} [style=dashed label="race" color=orange fontcolor=orange]
    runClnt -> {uAgent uProcess} [style=dashed label="race" color=orange fontcolor=orange]

    sAgent -> uRespq -> uProcess

    uAgent -> runClient [style=dashed label="fork" color=orange fontcolor=orange]
  }
}
