Since release 6 nobody publishes memberships, so a module placed since cannot serve its seat or reach a new state (the operator, 2026-10-25 22:31). The part publishes each membership on the assignments stream only when it differs from the one last published, composes from the manifest the wanted build names, and says a refused publish and tries again at the next event. Pins mesh-sdk 881da7f, whose composer grants mesh-grants that publish.
56 lines
1.9 KiB
Go
56 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
|
|
"github.com/nats-io/nats.go"
|
|
"github.com/nats-io/nats.go/jetstream"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/membership"
|
|
)
|
|
|
|
// memberships publishes each membership on the assignments stream, last per subject, over the one last read there
|
|
// (ExpectLastSequencePerSubject, so a membership another writer published meanwhile is not overwritten, issues 930 and
|
|
// 934), and reads the last one by a direct get of its subject. The one place the part publishes on the bus.
|
|
type memberships struct {
|
|
ctx context.Context
|
|
nc *nats.Conn
|
|
js jetstream.JetStream
|
|
}
|
|
|
|
func (m memberships) LastMembership(node, module string) ([]byte, uint64, bool, error) {
|
|
ctx, cancel := context.WithTimeout(m.ctx, requestWithin)
|
|
defer cancel()
|
|
msg, err := m.nc.RequestWithContext(ctx, membership.DirectGetSubject(node, module), nil)
|
|
if err != nil {
|
|
if errors.Is(err, context.DeadlineExceeded) {
|
|
err = fmt.Errorf("no answer in %s: a read the bus refuses is answered by none (%w)", requestWithin, err)
|
|
}
|
|
return nil, 0, false, err
|
|
}
|
|
switch status := msg.Header.Get("Status"); status {
|
|
case "":
|
|
case "404":
|
|
return nil, 0, false, nil
|
|
default:
|
|
return nil, 0, false, fmt.Errorf("the assignments stream answered %s %s", status, msg.Header.Get("Description"))
|
|
}
|
|
seq, err := strconv.ParseUint(msg.Header.Get("Nats-Sequence"), 10, 64)
|
|
if err != nil {
|
|
return nil, 0, false, fmt.Errorf("the membership of %s on %s carries no sequence", module, node)
|
|
}
|
|
return msg.Data, seq, true, nil
|
|
}
|
|
|
|
func (m memberships) PublishMembership(node, module string, body []byte, after uint64) error {
|
|
ctx, cancel := context.WithTimeout(m.ctx, requestWithin)
|
|
defer cancel()
|
|
if _, err := m.js.Publish(ctx, membership.Subject(node, module), body, jetstream.WithExpectLastSequencePerSubject(after)); err != nil {
|
|
return fmt.Errorf("the membership of %s on %s after sequence %d: %w", module, node, after, err)
|
|
}
|
|
return nil
|
|
}
|