Skip to content

Commit 9eafb14

Browse files
committed
fix(epp): keep metadata-less endpoints out of the p2p source maximum
The max-tracking loop counted endpoints the candidate loop later rejects for nil metadata, so a metadata-less endpoint reporting the pool's highest cached-token count inflated the maximum, every real endpoint fell outside the one-block band, and the source header was silently never set. One pass now collects usable sources and the maximum together, which also computes each endpoint's cached tokens once. Signed-off-by: nilig <nili.ifergan@gmail.com>
1 parent 6d21df7 commit 9eafb14

2 files changed

Lines changed: 42 additions & 7 deletions

File tree

pkg/epp/framework/plugins/requestcontrol/dataproducer/p2psource/producer.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,26 @@ func (p *Producer) attrKey() string {
161161
// mildly prefer a one-request-shorter queue, and starve deeply-queued
162162
// sources. No-op when no candidate holds any cached block.
163163
func (p *Producer) Produce(ctx context.Context, request *scheduling.InferenceRequest, endpoints []scheduling.Endpoint) error {
164+
// Endpoints without metadata cannot serve as sources (no address to
165+
// join), so they must not pin the pool maximum either: an inflated
166+
// maximum would exclude every real endpoint below.
167+
type sourceMatch struct {
168+
ep scheduling.Endpoint
169+
cached int
170+
blockSize int
171+
}
164172
maxCached := 0
173+
var matches []sourceMatch
165174
for _, ep := range endpoints {
166-
if cached := p.cachedTokenCount(ep); cached > maxCached {
175+
if ep.GetMetadata() == nil {
176+
continue
177+
}
178+
cached, blockSize := p.cachedTokens(ep)
179+
if cached == 0 {
180+
continue
181+
}
182+
matches = append(matches, sourceMatch{ep: ep, cached: cached, blockSize: blockSize})
183+
if cached > maxCached {
167184
maxCached = cached
168185
}
169186
}
@@ -174,14 +191,13 @@ func (p *Producer) Produce(ctx context.Context, request *scheduling.InferenceReq
174191
var cachedCounts []int
175192
var weights []float64
176193
total := 0.0
177-
for _, ep := range endpoints {
178-
cached, blockSize := p.cachedTokens(ep)
179-
if ep.GetMetadata() == nil || cached == 0 || cached+blockSize < maxCached {
194+
for _, m := range matches {
195+
if m.cached+m.blockSize < maxCached {
180196
continue
181197
}
182-
w := 1.0 / (1.0 + float64(waitingQueueSize(ep)))
183-
candidates = append(candidates, ep)
184-
cachedCounts = append(cachedCounts, cached)
198+
w := 1.0 / (1.0 + float64(waitingQueueSize(m.ep)))
199+
candidates = append(candidates, m.ep)
200+
cachedCounts = append(cachedCounts, m.cached)
185201
weights = append(weights, w)
186202
total += w
187203
}

pkg/epp/framework/plugins/requestcontrol/dataproducer/p2psource/producer_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,25 @@ func TestProduce_MissingMatchInfo_TreatedAsZero(t *testing.T) {
141141
assert.Equal(t, "10.0.0.2:8080", best.hostPort)
142142
}
143143

144+
// A metadata-less endpoint must not pin the pool maximum: it cannot serve as
145+
// a source itself, and an inflated maximum would exclude every real endpoint
146+
// and silently suppress the stash.
147+
func TestProduce_MetadataNilMax_DoesNotSuppressStash(t *testing.T) {
148+
ctx := utils.NewTestContext(t)
149+
p := New("test", Config{MinCachedTokenDelta: 1})
150+
151+
noMD := scheduling.NewEndpoint(nil, nil, nil)
152+
noMD.Put(p.prefixMatchDataKey.String(),
153+
attrprefix.NewPrefixCacheMatchInfo(10, 4, testBlockSize).WithCachedBlockCount(10))
154+
155+
req := &scheduling.InferenceRequest{RequestID: "req-nil-md"}
156+
require.NoError(t, p.Produce(ctx, req, []scheduling.Endpoint{noMD, endpoint(p, "pod-b", "10.0.0.2", 2)}))
157+
158+
best, ok := scheduling.ReadRequestAttribute[*bestMatchPeer](req, p.attrKey())
159+
require.True(t, ok)
160+
assert.Equal(t, "10.0.0.2:8080", best.hostPort)
161+
}
162+
144163
// Best peer exceeds the decode pod's cached tokens by >= delta: header set.
145164
func TestPreRequest_SetsKVCacheSourceHeader(t *testing.T) {
146165
ctx := utils.NewTestContext(t)

0 commit comments

Comments
 (0)