72 lines
2.3 KiB
Go
72 lines
2.3 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"github.com/novox/mesh-host/internal/link"
|
|
)
|
|
|
|
// settledEvent is where the status view says a module has settled on a node: its have reached its want, running and healthy
|
|
// (design 47; the view's `settled`, said once for a module on a node at one composition). The engine hears it for every module
|
|
// and tells its agent, which tries again, once per settled, a failed apply that waits on that module as the holder of the store
|
|
// its image comes from (design 51 *distribution's first delivery*, issue 1966 ENG-11). The grants part grants the engine this
|
|
// subject (NodeAgentHears); a refused subscription is said, and made again when the next link opens.
|
|
const settledEvent = "mesh.mod.mesh-delivery-view.event.settled"
|
|
|
|
// settledBody is what of the event the engine reads: the module that settled, on whichever node.
|
|
type settledBody struct {
|
|
Module string `json:"module"`
|
|
}
|
|
|
|
// settledTold is who is told a holder has settled.
|
|
type settledTold interface{ Settled(holder string) }
|
|
|
|
// followSettled hears the status view's `settled` on every link, never on a timer, until ctx ends. now names the agent running
|
|
// now (nil while the node agent begins again): a settled heard while there is none is not lost for it, since a new agent applies
|
|
// again every have that failed at its start.
|
|
func followSettled(ctx context.Context, session *link.Session, now func() settledTold, say link.Announce) {
|
|
said := ""
|
|
for ctx.Err() == nil {
|
|
linked, cancel, err := session.WhenLinked(ctx)
|
|
if err != nil {
|
|
return
|
|
}
|
|
events, stop, herr := session.Hear(settledEvent)
|
|
if herr != nil {
|
|
if line := fmt.Sprintf("a store settling is not heard yet (%s: %v): a failed pull waits for the next link, or for compose", settledEvent, herr); line != said {
|
|
said = line
|
|
say(line)
|
|
}
|
|
} else {
|
|
said = ""
|
|
listen(linked, events, now, say)
|
|
stop()
|
|
}
|
|
<-linked.Done()
|
|
cancel()
|
|
}
|
|
}
|
|
|
|
// listen tells the agent each settled it hears, until the link ends.
|
|
func listen(linked context.Context, events <-chan []byte, now func() settledTold, say link.Announce) {
|
|
for {
|
|
select {
|
|
case <-linked.Done():
|
|
return
|
|
case raw, ok := <-events:
|
|
if !ok {
|
|
return
|
|
}
|
|
var b settledBody
|
|
if json.Unmarshal(raw, &b) != nil || b.Module == "" {
|
|
continue
|
|
}
|
|
if told := now(); told != nil {
|
|
told.Settled(b.Module)
|
|
}
|
|
}
|
|
}
|
|
}
|