package broker import ( "fmt" "strings" "github.com/novox/mesh-controller/internal/envfile" ) // Whether this mesh's own traffic is on the bus being built. // // **One switch, read in one place** (novox/hq ADR 0116 step 5). Every seam the bus change went // behind ships both implementations, and until the rollout every one of them chooses the bus the // mesh runs on today. This is what the rollout flips, and it is deliberately a single fact rather // than a fact per component: a controller whose outbound is on one bus and whose inbound is on the // other is a mesh that hears nothing, and no test of either half would catch it. // NATSVar is where the controller finds the bus being built. Unset is the ordinary case and means // the mesh runs on the bus it has always run on. const NATSVar = "MESH_BUS_NATS" // OnNATS is the address of the bus being built, and whether the mesh is on it. // // Read from the node's own settings rather than baked in, for the reason the broker's address is // (novox/hq 04-ISSUES/102): an address recorded once does not follow a node's ports. func OnNATS() (address string, on bool, err error) { address, err = envfile.Placed(NATSVar) if err != nil { return "", false, err } address = strings.TrimSpace(address) if address == "" { return "", false, nil } return address, true, nil } // MustBeOneBus refuses a configuration that names both buses for the mesh's own traffic. // // **Both clients ship and that is the point; both being live is not.** The rollout moves every node // at once (ADR 0116 step 5): a mesh half on each is one where a declaration goes out on one bus and // the report comes back on the other, and nothing anywhere says so — every component would log // success. Refused at start, where it can be said in one sentence. func MustBeOneBus(amqp, nats string) error { if strings.TrimSpace(amqp) != "" && strings.TrimSpace(nats) != "" { return fmt.Errorf( "this control plane is told about both buses (%s and %s) and can only be on one. A mesh "+ "half on each is one where a declaration goes out on one and the report comes back "+ "on the other, and every component reports success while it happens. The rollout "+ "moves every node at once: unset %s to stay, or unset %s to move", AMQPVarName, NATSVar, NATSVar, AMQPVarName) } return nil } // AMQPVarName is the variable naming the bus the mesh runs on today. Named here rather than // imported from the link package, for the one direction of dependency. const AMQPVarName = "MESH_BROKER_AMQP"