82 lines
3.2 KiB
Go
82 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/nats-io/nats.go"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
"github.com/novox/mesh-controller/internal/link"
|
|
)
|
|
|
|
// performSeatPasses records, in the send that finds them, the new holder of each seat held once whose holder on record is
|
|
// assigned nowhere and which has exactly one claimant able to hold it (the composition names them: catalogue.SeatsToPassOn,
|
|
// novox/hq ADR 0449 §4, issue 1317), and writes the controller's own hand act for each. A failed write is said and leaves the
|
|
// record as it was: a send is never refused for it. It answers whether it recorded any.
|
|
func performSeatPasses(ctx context.Context, sp seatPassing, passes []catalogue.SeatPass) bool {
|
|
did := false
|
|
for _, p := range passes {
|
|
moved, err := sp.pass(ctx, p)
|
|
if err != nil {
|
|
fmt.Fprintf(sp.say, "%s could not be passed from %s on %s to %s on %s: %v\n", p.Seat.Name,
|
|
p.From.Module, p.From.Node, p.To.Module, p.To.Node, err)
|
|
continue
|
|
}
|
|
if !moved {
|
|
continue // another composition passed it first, and wrote the act
|
|
}
|
|
did = true
|
|
if err := sp.act(ctx, p); err != nil {
|
|
fmt.Fprintf(sp.say, "%s passed from %s on %s to %s on %s, and the hand act could NOT be recorded: %v\n",
|
|
p.Seat.Name, p.From.Module, p.From.Node, p.To.Module, p.To.Node, err)
|
|
}
|
|
}
|
|
return did
|
|
}
|
|
|
|
// seatPassing is what passing seats on needs of the outside: the record's compare-and-set, and the hand act.
|
|
type seatPassing struct {
|
|
pass func(ctx context.Context, p catalogue.SeatPass) (bool, error)
|
|
act func(ctx context.Context, p catalogue.SeatPass) error
|
|
say io.Writer
|
|
}
|
|
|
|
// seatPassHandAct is the controller's own entry for a pass: it is the act that puts the holder on record,
|
|
// where a person's `seat --to` would have, so the record of who held what stays complete (ADR 0449 §4).
|
|
func seatPassHandAct(p catalogue.SeatPass) link.HandAct {
|
|
return link.HandAct{
|
|
By: "the controller",
|
|
Verb: "seat",
|
|
Args: []string{p.Seat.Name, "--to", p.To.Node + "/" + p.To.Module, "--was", p.From.Node + "/" + p.From.Module},
|
|
Why: fmt.Sprintf("%s on %s, the holder on record of %s, is assigned on no machine, and %s on %s is the only "+
|
|
"assignment that claims it and can hold it (ADR 0449 §4)", p.From.Module, p.From.Node, p.Seat.Name,
|
|
p.To.Module, p.To.Node),
|
|
Cause: "seat-passed",
|
|
Outcome: "done",
|
|
}
|
|
}
|
|
|
|
// seatPassingOn is how a send passes a seat: against the store's record, with the hand act on the bus; on a throwaway mesh
|
|
// (the merge gate's) the record is kept in its store and no act is written, for there is no bus to write it to.
|
|
func seatPassingOn(inv *inventory.Inventory, w io.Writer) seatPassing {
|
|
sp := seatPassing{
|
|
say: w,
|
|
pass: func(ctx context.Context, p catalogue.SeatPass) (bool, error) {
|
|
return inv.PassSeat(ctx, p.Seat.Name, p.Seat.Scope, p.From, p.To)
|
|
},
|
|
act: func(ctx context.Context, p catalogue.SeatPass) error {
|
|
return onTheBus(func(conn *nats.Conn) error {
|
|
_, err := link.RecordHandAct(ctx, conn, seatPassHandAct(p))
|
|
return err
|
|
})
|
|
},
|
|
}
|
|
if inv.Throwaway() {
|
|
sp.act = func(context.Context, catalogue.SeatPass) error { return nil }
|
|
}
|
|
return sp
|
|
}
|