mesh/delivery-group group feat/r4d rejected: a member's own check failed
mesh/repo-check out of date: judged beside mesh-catalog#434 at c948f3a61c74, it is now at 7451e7edf4e5; judged again on a recheck or when it is merged
mesh/merge-gate group feat/r4d: composed again for the group's new heads
mesh/delivery superseded: a newer head of the same pull request
mesh/check failed: unit: i3/cmd/i3-tools.TestTheMainFileAndEveryModulesContributionLoadTogether: manifest_test.go:247: expected the launcher, clipboar…
A bundle is built only from its module's directory (ADR 0480 clause 4), so the proxy leaves examples/ and the controller's internal/broker; the broker keeps no second copy of what the proxy shares with mesh-sdk. The image and its Dockerfile go, and a test holds that only build-agent declares one (clause 11).
86 lines
3.0 KiB
Go
86 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"strings"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"github.com/nats-io/nats.go"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/membership"
|
|
"git.novox.be/novox/mesh-sdk/go/process"
|
|
)
|
|
|
|
// What the mesh issued this proxy, read on the bus (novox/hq ADR 0160, ADR 0167).
|
|
//
|
|
// **The proxy is told, not left to work it out.** Its membership carries the routes it is given —
|
|
// the same contributions its file is written from — and every machine's address on the private
|
|
// network, which is who may be served an internal name. Read once at connect and followed, so a
|
|
// route added or a machine joining reaches a running proxy without a restart.
|
|
|
|
// followMembership connects with the credential in path and applies every membership the mesh
|
|
// issues this proxy. It retries the first connection for as long as it takes: a proxy that started
|
|
// before the bus keeps serving the file, and takes the bus when it answers.
|
|
func followMembership(path string, held *table, fromBus *atomic.Bool) {
|
|
for {
|
|
err := followOnce(path, held, fromBus)
|
|
if err == nil {
|
|
return
|
|
}
|
|
log.Printf("cannot follow this proxy's membership, serving the file meanwhile: %v", err)
|
|
time.Sleep(30 * time.Second)
|
|
}
|
|
}
|
|
|
|
func followOnce(path string, held *table, fromBus *atomic.Bool) error {
|
|
account, err := process.ReadAccount(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
conn, err := process.Connect(account, nats.Name(account.Node+"."+account.Module))
|
|
if err != nil {
|
|
return fmt.Errorf("connecting to the bus at %s: %w", membership.BareAddress(account.URL), err)
|
|
}
|
|
subject := membership.Subject(account.Node, account.Module)
|
|
err = conn.FollowMembership(func(issued membership.Membership) {
|
|
if took := applyMembership(issued, held); took && !fromBus.Swap(true) {
|
|
log.Printf("routes now come from this proxy's membership on %s", subject)
|
|
}
|
|
}, func(err error) { log.Print(err) })
|
|
if err != nil {
|
|
conn.Close()
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// applyMembership serves what a membership says, and says whether it said anything about routes.
|
|
//
|
|
// A membership with no routes in it is one from a controller older than ADR 0167, and the file stays
|
|
// the source rather than every route being withdrawn because a field was absent.
|
|
func applyMembership(issued membership.Membership, held *table) bool {
|
|
raw, carries := issued.Receives["route"]
|
|
if !carries {
|
|
return false
|
|
}
|
|
var contributions []contribution
|
|
if err := json.Unmarshal(raw, &contributions); err != nil {
|
|
log.Printf("the routes in this proxy's membership are not contributions, keeping what is served: %v", err)
|
|
return false
|
|
}
|
|
inside, err := sourcesOf(issued.Mesh)
|
|
if err != nil {
|
|
log.Printf("the mesh in this proxy's membership is unreadable, keeping what is served: %v", err)
|
|
return false
|
|
}
|
|
routes, public := routesOf(contributions)
|
|
held.set(routes, public)
|
|
held.setInside(inside)
|
|
log.Printf("serving %d route(s) from the membership, internal names to %d machine(s): %s",
|
|
len(routes), len(inside), strings.Join(held.names(), ", "))
|
|
return true
|
|
}
|