notify.webhooks sends signed JSON or Slack-compatible messages, queued, retried, de-duplicated hourly; ctl notify test checks each webhook. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
47 lines
1.3 KiB
Go
47 lines
1.3 KiB
Go
package reconciler
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"gitea.mynodes.xyz/ilker/llmgw/internal/control/inventory"
|
|
"gitea.mynodes.xyz/ilker/llmgw/internal/notify"
|
|
"gitea.mynodes.xyz/ilker/llmgw/internal/notify/notifytest"
|
|
)
|
|
|
|
func TestParkingAModelTellsSomeone(t *testing.T) {
|
|
h := newHarness(t, testModel(1), gpuNode("1", 8))
|
|
n, sent := notifytest.Catch(t)
|
|
h.r.SetNotifier(n)
|
|
failRepeatedly(t, h, DefaultConfig().ParkAfter, "unknown model architecture: 'ggmlc'")
|
|
h.advance(DefaultConfig().MaxBackoff + time.Second)
|
|
h.r.Reconcile(t.Context())
|
|
|
|
got := sent()
|
|
if len(got) != 1 || got[0].Kind != notify.ModelParked || got[0].Subject != "llama" {
|
|
t.Fatalf("sent %+v, want one model_parked for llama", got)
|
|
}
|
|
}
|
|
|
|
func TestLosingANodeTellsSomeone(t *testing.T) {
|
|
h := newHarness(t, testModel(1), gpuNode("1", 8), gpuNode("2", 8))
|
|
n, sent := notifytest.Catch(t)
|
|
h.r.SetNotifier(n)
|
|
h.r.Reconcile(t.Context())
|
|
h.markReady()
|
|
h.r.Reconcile(t.Context())
|
|
|
|
for _, d := range []time.Duration{20 * time.Second, 90 * time.Second} {
|
|
h.clock.advance(d)
|
|
touchAt(h.inv, "2", h.clock.now())
|
|
h.r.Reconcile(t.Context())
|
|
}
|
|
if n, _ := h.inv.Get("1"); n.State != inventory.Lost {
|
|
t.Fatalf("node 1 is %s", n.State)
|
|
}
|
|
got := sent()
|
|
if len(got) != 1 || got[0].Kind != notify.NodeLost || got[0].Subject != "1" {
|
|
t.Fatalf("sent %+v, want one node_lost for 1", got)
|
|
}
|
|
}
|