Files
wehub-resource-sync 1b8708893a
Security Scan / tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:12:26 +08:00

213 lines
7.0 KiB
Go

package nodes
import (
"context"
"fmt"
"sync"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
pb "github.com/mudler/LocalAI/pkg/grpc/proto"
)
// --- fakeModelRouterForSmartRouter implements ModelRouter ---
type fakeModelRouterForSmartRouter struct {
mu sync.Mutex
node *BackendNode
nodeModel *NodeModel
findErr error
decrementCalled map[string]int // "nodeID:model" -> count
}
func newFakeModelRouterForSmartRouter() *fakeModelRouterForSmartRouter {
return &fakeModelRouterForSmartRouter{
decrementCalled: make(map[string]int),
}
}
func (f *fakeModelRouterForSmartRouter) FindAndLockNodeWithModel(_ context.Context, _ string, _ []string, _ *RoutePreference) (*BackendNode, *NodeModel, error) {
f.mu.Lock()
defer f.mu.Unlock()
return f.node, f.nodeModel, f.findErr
}
func (f *fakeModelRouterForSmartRouter) DecrementInFlight(_ context.Context, nodeID, modelName string, _ int) error {
f.mu.Lock()
defer f.mu.Unlock()
f.decrementCalled[nodeID+":"+modelName]++
return nil
}
func (f *fakeModelRouterForSmartRouter) IncrementInFlight(_ context.Context, _, _ string, _ int) error {
return nil
}
func (f *fakeModelRouterForSmartRouter) RemoveNodeModel(_ context.Context, _, _ string, _ int) error {
return nil
}
func (f *fakeModelRouterForSmartRouter) RemoveAllNodeModelReplicas(_ context.Context, _, _ string) error {
return nil
}
func (f *fakeModelRouterForSmartRouter) TouchNodeModel(_ context.Context, _, _ string, _ int) {}
func (f *fakeModelRouterForSmartRouter) SetNodeModel(_ context.Context, _, _ string, _ int, _, _ string, _ int) error {
return nil
}
func (f *fakeModelRouterForSmartRouter) SetNodeModelLoadInfo(_ context.Context, _, _ string, _ int, _ string, _ []byte) error {
return nil
}
func (f *fakeModelRouterForSmartRouter) UpsertModelLoadInfo(_ context.Context, _, _ string, _ []byte) error {
return nil
}
func (f *fakeModelRouterForSmartRouter) GetModelLoadInfo(_ context.Context, _ string) (string, []byte, error) {
return "", nil, fmt.Errorf("not found")
}
func (f *fakeModelRouterForSmartRouter) NextFreeReplicaIndex(_ context.Context, _, _ string, _ int) (int, error) {
return 0, nil
}
func (f *fakeModelRouterForSmartRouter) CountReplicasOnNode(_ context.Context, _, _ string) (int, error) {
return 0, nil
}
func (f *fakeModelRouterForSmartRouter) FindNodeWithVRAM(_ context.Context, _ uint64) (*BackendNode, error) {
return nil, nil
}
func (f *fakeModelRouterForSmartRouter) FindIdleNode(_ context.Context) (*BackendNode, error) {
return nil, nil
}
func (f *fakeModelRouterForSmartRouter) FindLeastLoadedNode(_ context.Context) (*BackendNode, error) {
return nil, nil
}
func (f *fakeModelRouterForSmartRouter) FindGlobalLRUModelWithZeroInFlight(_ context.Context) (*NodeModel, error) {
return nil, nil
}
func (f *fakeModelRouterForSmartRouter) FindLRUModel(_ context.Context, _ string) (*NodeModel, error) {
return nil, nil
}
func (f *fakeModelRouterForSmartRouter) Get(_ context.Context, nodeID string) (*BackendNode, error) {
f.mu.Lock()
defer f.mu.Unlock()
if f.node != nil && f.node.ID == nodeID {
return f.node, nil
}
return nil, nil
}
func (f *fakeModelRouterForSmartRouter) GetModelScheduling(_ context.Context, _ string) (*ModelSchedulingConfig, error) {
return nil, nil
}
func (f *fakeModelRouterForSmartRouter) FindNodesBySelector(_ context.Context, _ map[string]string) ([]BackendNode, error) {
return nil, nil
}
func (f *fakeModelRouterForSmartRouter) FindNodesWithFreeSlot(_ context.Context, _ string, _ []string) ([]BackendNode, error) {
return nil, nil
}
func (f *fakeModelRouterForSmartRouter) ReserveVRAM(_ context.Context, _ string, _ uint64) error {
return nil
}
func (f *fakeModelRouterForSmartRouter) ReleaseVRAM(_ context.Context, _ string, _ uint64) error {
return nil
}
func (f *fakeModelRouterForSmartRouter) FindNodeWithVRAMFromSet(_ context.Context, _ uint64, _ []string) (*BackendNode, error) {
return nil, nil
}
func (f *fakeModelRouterForSmartRouter) FindIdleNodeFromSet(_ context.Context, _ []string) (*BackendNode, error) {
return nil, nil
}
func (f *fakeModelRouterForSmartRouter) FindLeastLoadedNodeFromSet(_ context.Context, _ []string) (*BackendNode, error) {
return nil, nil
}
func (f *fakeModelRouterForSmartRouter) GetNodeLabels(_ context.Context, _ string) ([]NodeLabel, error) {
return nil, nil
}
func (f *fakeModelRouterForSmartRouter) FindNodesWithModel(_ context.Context, _ string) ([]BackendNode, error) {
return nil, nil
}
func (f *fakeModelRouterForSmartRouter) LoadedReplicaStats(_ context.Context, _ string, _ []string) ([]ReplicaCandidate, error) {
return nil, nil
}
// Compile-time check
var _ ModelRouter = (*fakeModelRouterForSmartRouter)(nil)
var _ = Describe("ModelRouterAdapter", func() {
Describe("ReleaseModel", func() {
It("calls stored release function", func() {
adapter := &ModelRouterAdapter{
release: make(map[string]func()),
}
released := false
adapter.release["my-model"] = func() { released = true }
adapter.ReleaseModel("my-model")
Expect(released).To(BeTrue())
// Release function should be removed after calling
Expect(adapter.release).NotTo(HaveKey("my-model"))
})
It("is no-op for unknown model", func() {
adapter := &ModelRouterAdapter{
release: make(map[string]func()),
}
// Should not panic
adapter.ReleaseModel("nonexistent-model")
Expect(adapter.release).To(BeEmpty())
})
})
Describe("Route", func() {
It("delegates to SmartRouter and stores release func", func() {
fakeNode := &BackendNode{
ID: "node-1",
Name: "test-node",
Address: "10.0.0.1:50051",
}
fakeNM := &NodeModel{
NodeID: "node-1",
ModelName: "test-model",
}
fakeReg := newFakeModelRouterForSmartRouter()
fakeReg.node = fakeNode
fakeReg.nodeModel = fakeNM
// The fake gRPC client that SmartRouter will use for health check
factory := newFakeBackendClientFactory()
factory.setClient("10.0.0.1:50051", &fakeBackendClient{healthy: true})
sr := NewSmartRouter(fakeReg, SmartRouterOptions{
ClientFactory: factory,
})
adapter := NewModelRouterAdapter(sr)
opts := &pb.ModelOptions{Model: "test-model"}
m, err := adapter.Route(context.Background(), "llama-cpp", "test-model", "test-model", "model.gguf", opts, false)
Expect(err).NotTo(HaveOccurred())
Expect(m).NotTo(BeNil())
Expect(m.ID).To(Equal("test-model"))
// Verify release function was stored
adapter.mu.Lock()
_, hasRelease := adapter.release["test-model"]
adapter.mu.Unlock()
Expect(hasRelease).To(BeTrue())
// The initial in-flight reservation is released via OnFirstComplete after
// the first inference call, not during ReleaseModel. ReleaseModel only
// closes the client.
fakeReg.mu.Lock()
countBeforeRelease := fakeReg.decrementCalled["node-1:test-model"]
fakeReg.mu.Unlock()
Expect(countBeforeRelease).To(Equal(0))
adapter.ReleaseModel("test-model")
fakeReg.mu.Lock()
countAfterRelease := fakeReg.decrementCalled["node-1:test-model"]
fakeReg.mu.Unlock()
Expect(countAfterRelease).To(Equal(0))
})
})
})