|
| 1 | +package prefixcache_test |
| 2 | + |
| 3 | +import ( |
| 4 | + "time" |
| 5 | + |
| 6 | + . "github.com/onsi/ginkgo/v2" |
| 7 | + . "github.com/onsi/gomega" |
| 8 | + |
| 9 | + "github.com/mudler/LocalAI/core/services/messaging" |
| 10 | + "github.com/mudler/LocalAI/core/services/nodes/prefixcache" |
| 11 | +) |
| 12 | + |
| 13 | +var _ prefixcache.Provider = (*prefixcache.ReportedIndex)(nil) |
| 14 | + |
| 15 | +var _ = Describe("ReportedIndex", func() { |
| 16 | + var idx *prefixcache.ReportedIndex |
| 17 | + |
| 18 | + BeforeEach(func() { idx = prefixcache.NewReportedIndex() }) |
| 19 | + |
| 20 | + It("routes to the replica with the longest reported prefix", func() { |
| 21 | + idx.Apply(messaging.PrefixCacheResidencyEvent{Operation: messaging.PrefixCacheStore, Model: "m", NodeID: "A", Replica: 0, Chain: []uint64{1, 2}}) |
| 22 | + idx.Apply(messaging.PrefixCacheResidencyEvent{Operation: messaging.PrefixCacheStore, Model: "m", NodeID: "B", Replica: 0, Chain: []uint64{1, 2, 3, 4}}) |
| 23 | + d := idx.Decide("m", []uint64{1, 2, 3, 9}, []prefixcache.ReplicaKey{rk("A", 0), rk("B", 0)}, t0) |
| 24 | + Expect(d.HasHot).To(BeTrue()) |
| 25 | + Expect(d.Hot).To(Equal(rk("B", 0))) |
| 26 | + Expect(d.MatchRatio).To(Equal(0.75)) |
| 27 | + }) |
| 28 | + |
| 29 | + It("removes only the announced residency", func() { |
| 30 | + for _, chain := range [][]uint64{{1, 2}, {7, 8}} { |
| 31 | + idx.Apply(messaging.PrefixCacheResidencyEvent{Operation: messaging.PrefixCacheStore, Model: "m", NodeID: "A", Replica: 0, Chain: chain}) |
| 32 | + } |
| 33 | + idx.Apply(messaging.PrefixCacheResidencyEvent{Operation: messaging.PrefixCacheRemove, Model: "m", NodeID: "A", Replica: 0, Chain: []uint64{1, 2}}) |
| 34 | + Expect(idx.Decide("m", []uint64{1, 2}, []prefixcache.ReplicaKey{rk("A", 0)}, t0).HasHot).To(BeFalse()) |
| 35 | + Expect(idx.Decide("m", []uint64{7, 8}, []prefixcache.ReplicaKey{rk("A", 0)}, t0).HasHot).To(BeTrue()) |
| 36 | + }) |
| 37 | + |
| 38 | + It("clears every residency for one replica only", func() { |
| 39 | + idx.Apply(messaging.PrefixCacheResidencyEvent{Operation: messaging.PrefixCacheStore, Model: "m", NodeID: "A", Replica: 0, Chain: []uint64{1, 2}}) |
| 40 | + idx.Apply(messaging.PrefixCacheResidencyEvent{Operation: messaging.PrefixCacheStore, Model: "m", NodeID: "B", Replica: 0, Chain: []uint64{3, 4}}) |
| 41 | + idx.Apply(messaging.PrefixCacheResidencyEvent{Operation: messaging.PrefixCacheClear, Model: "m", NodeID: "A", Replica: 0}) |
| 42 | + candidates := []prefixcache.ReplicaKey{rk("A", 0), rk("B", 0)} |
| 43 | + Expect(idx.Decide("m", []uint64{1, 2}, candidates, t0).HasHot).To(BeFalse()) |
| 44 | + Expect(idx.Decide("m", []uint64{3, 4}, candidates, t0).Hot).To(Equal(rk("B", 0))) |
| 45 | + }) |
| 46 | + |
| 47 | + It("ignores guessed request observations and keeps cold ordering deterministic", func() { |
| 48 | + Expect(idx.Observe("m", []uint64{1, 2}, rk("A", 0), t0)).To(BeFalse()) |
| 49 | + d := idx.Decide("m", []uint64{1, 2}, []prefixcache.ReplicaKey{rk("B", 1), rk("A", 1), rk("A", 0)}, time.Now()) |
| 50 | + Expect(d.HasHot).To(BeFalse()) |
| 51 | + Expect(d.ColdOrder).To(Equal([]prefixcache.ReplicaKey{rk("A", 0), rk("A", 1), rk("B", 1)})) |
| 52 | + }) |
| 53 | +}) |
0 commit comments