Take the composition, catalogue and validator from mesh-sdk and delete the controller's copies (design 47 R4b, issues 1337, 1381-1391) #405

Merged
mesh-tools merged 45 commits from feat/r4b-sdk-users into main 2026-10-20 12:03:23 +00:00
Showing only changes of commit b280b9de10 - Show all commits
+39 -5
View File
@@ -6,6 +6,7 @@ import (
"errors"
"reflect"
"strings"
"sync"
"testing"
"time"
@@ -116,11 +117,30 @@ func contains(s, sub string) bool { return strings.Contains(s, sub) }
// fakeWatch is one bucket's watch of the key, fed by the test.
type fakeWatch struct {
updates chan jetstream.KeyValueEntry
stopped bool
done chan struct{} // closed when the watch is stopped
once sync.Once
}
func newFakeWatch() *fakeWatch {
return &fakeWatch{updates: make(chan jetstream.KeyValueEntry, 1), done: make(chan struct{})}
}
// handled returns once the watch has taken the entry fed before it and finished with it. The channel holds one entry,
// so the second filler (an entry the watch passes over) can only be sent after the first was taken, which the watch
// does only after it handled the entry before it. It needs a watch that is still listening: after a move it is not.
func (f *fakeWatch) handled(t *testing.T) {
t.Helper()
for range 2 {
select {
case f.updates <- fakeEntry{value: "not a key"}:
case <-time.After(2 * time.Second):
t.Fatal("the watch took no entry")
}
}
}
func (f *fakeWatch) Updates() <-chan jetstream.KeyValueEntry { return f.updates }
func (f *fakeWatch) Stop() error { f.stopped = true; return nil }
func (f *fakeWatch) Stop() error { f.once.Do(func() { close(f.done) }); return nil }
type fakeEntry struct {
jetstream.KeyValueEntry
@@ -138,7 +158,7 @@ func TestARunningChecksWatchFindsItsKeyInTheGatesBucketOrTodays(t *testing.T) {
run := func(exist ...string) (map[string]*fakeWatch, chan PullKey, func(), error) {
watches := map[string]*fakeWatch{}
for _, b := range exist {
watches[b] = &fakeWatch{updates: make(chan jetstream.KeyValueEntry, 1)}
watches[b] = newFakeWatch()
}
moved := make(chan PullKey, 2)
stop, err := watchPullIn(t.Context(), req.Check.Pulls, func(_ context.Context, bucket string) (pullWatcher, error) {
@@ -182,14 +202,28 @@ func TestARunningChecksWatchFindsItsKeyInTheGatesBucketOrTodays(t *testing.T) {
t.Fatal(err)
}
watches["mesh-delivery-gate_pulls"].updates <- fakeEntry{value: `{"head":"old","trunk":"t","verdict":"pass"}`}
if _, ok := wait(moved); ok {
watches["mesh-delivery-gate_pulls"].handled(t)
select {
case <-moved:
t.Error("a verdict alone moved the check")
default:
}
// Both buckets hear the move; the second watch is done (stopped) once it has handled its entry, and by then a
// second telling would be in the channel.
watches["mesh-delivery-gate_pulls"].updates <- fakeEntry{value: `{"head":"newer","trunk":"t"}`}
watches["mesh-delivery_pulls"].updates <- fakeEntry{value: `{"head":"newer","trunk":"t"}`}
wait(moved)
if _, ok := wait(moved); ok {
for b, w := range watches {
select {
case <-w.done:
case <-time.After(2 * time.Second):
t.Errorf("the watch of %s did not end after the move", b)
}
}
select {
case <-moved:
t.Error("a move was told twice")
default:
}
stop()
if _, _, _, err := run(); err == nil {