Skip to content

Commit 8e9f7a3

Browse files
committed
refactor: replace MayConsumePlugin with OptionalConsumes in ConsumerPlugin
Signed-off-by: Alok Behera <alokbeherak061@gmail.com>
1 parent 3d70e5d commit 8e9f7a3

7 files changed

Lines changed: 50 additions & 37 deletions

File tree

pkg/epp/datalayer/data_graph.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ func CreateMissingDataProducers(ctx context.Context, defaultProducerRegistry map
8181
}
8282
}
8383

84-
// Warn about optional keys (MayConsume) with no producer — no error, just a warning.
84+
// Warn about optional keys with no producer — no error, just a warning.
8585
for _, p := range handle.GetAllPlugins() {
86-
if mayConsumer, ok := p.(plugin.MayConsumePlugin); ok {
87-
for key := range mayConsumer.MayConsume() {
86+
if consumer, ok := p.(plugin.ConsumerPlugin); ok {
87+
for key := range consumer.OptionalConsumes() {
8888
if !producedKeys[key.String()] {
8989
logger.Info("Warning: optional data key has no producer, plugin will use fallback",
9090
"plugin", p.TypedName().Name, "dataKey", key.String())

pkg/epp/datalayer/data_graph_test.go

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ func (m *mockDataProducerP) Consumes() map[fwkplugin.DataKey]any {
6262
return m.consumes
6363
}
6464

65+
func (m *mockDataProducerP) OptionalConsumes() map[fwkplugin.DataKey]any { return nil }
66+
6567
func (m *mockDataProducerP) Produce(ctx context.Context, request *fwksched.InferenceRequest, endpoints []fwksched.Endpoint) error {
6668
endpoints[0].Put(mockProducedDataKey, &mockProducedDataType{value: 42})
6769
return nil
@@ -92,6 +94,8 @@ func (m *MockConsumerFairnessPolicy) Consumes() map[fwkplugin.DataKey]any {
9294
return m.consumes
9395
}
9496

97+
func (m *MockConsumerFairnessPolicy) OptionalConsumes() map[fwkplugin.DataKey]any { return nil }
98+
9599
type MockSchedulingPlugin struct {
96100
fwksched.Scorer
97101
consumes map[fwkplugin.DataKey]any
@@ -105,6 +109,8 @@ func (m *MockSchedulingPlugin) Consumes() map[fwkplugin.DataKey]any {
105109
return m.consumes
106110
}
107111

112+
func (m *MockSchedulingPlugin) OptionalConsumes() map[fwkplugin.DataKey]any { return nil }
113+
108114
func TestValidatePluginExecutionOrder(t *testing.T) {
109115
dkA := fwkplugin.NewDataKey("keyA", "mock")
110116
// Request control plugin that produces data.
@@ -429,27 +435,29 @@ func TestCreateMissingDataProducers(t *testing.T) {
429435
}
430436
}
431437

432-
// mockMayConsumerPlugin is a plugin that optionally consumes certain data keys.
438+
// mockMayConsumerPlugin is a plugin that only optionally consumes certain data keys.
433439
type mockMayConsumerPlugin struct {
434-
name string
435-
mayConsume map[fwkplugin.DataKey]any
440+
name string
441+
optionalConsumes map[fwkplugin.DataKey]any
436442
}
437443

438444
func (m *mockMayConsumerPlugin) TypedName() fwkplugin.TypedName {
439445
return fwkplugin.TypedName{Name: m.name, Type: "mock"}
440446
}
441447

442-
func (m *mockMayConsumerPlugin) MayConsume() map[fwkplugin.DataKey]any {
443-
return m.mayConsume
448+
func (m *mockMayConsumerPlugin) Consumes() map[fwkplugin.DataKey]any { return nil }
449+
450+
func (m *mockMayConsumerPlugin) OptionalConsumes() map[fwkplugin.DataKey]any {
451+
return m.optionalConsumes
444452
}
445453

446-
// mockMixedConsumerPlugin is a plugin that has both required Consumes and optional MayConsume.
454+
// mockMixedConsumerPlugin is a plugin that has both required Consumes and optional OptionalConsumes.
447455
// This models a real plugin like prefix cache scorer — requires prefix-match data,
448456
// but optionally uses tokenized input and falls back to raw text if unavailable.
449457
type mockMixedConsumerPlugin struct {
450-
name string
451-
consumes map[fwkplugin.DataKey]any
452-
mayConsume map[fwkplugin.DataKey]any
458+
name string
459+
consumes map[fwkplugin.DataKey]any
460+
optionalConsumes map[fwkplugin.DataKey]any
453461
}
454462

455463
func (m *mockMixedConsumerPlugin) TypedName() fwkplugin.TypedName {
@@ -460,15 +468,15 @@ func (m *mockMixedConsumerPlugin) Consumes() map[fwkplugin.DataKey]any {
460468
return m.consumes
461469
}
462470

463-
func (m *mockMixedConsumerPlugin) MayConsume() map[fwkplugin.DataKey]any {
464-
return m.mayConsume
471+
func (m *mockMixedConsumerPlugin) OptionalConsumes() map[fwkplugin.DataKey]any {
472+
return m.optionalConsumes
465473
}
466474

467475
func TestCreateMissingDataProducers_MayConsume(t *testing.T) {
468476
producerTypeA := "producer-a"
469477
keyA := fwkplugin.NewDataKey("keyA", producerTypeA)
470478

471-
producerAFactory := fwkplugin.FactoryFunc(func(name string, _ json.RawMessage, handle fwkplugin.Handle) (fwkplugin.Plugin, error) {
479+
producerAFactory := fwkplugin.FactoryFunc(func(name string, _ *json.Decoder, handle fwkplugin.Handle) (fwkplugin.Plugin, error) {
472480
return &mockDataProducerP{name: name, produces: map[fwkplugin.DataKey]any{keyA: nil}}, nil
473481
})
474482

@@ -479,40 +487,40 @@ func TestCreateMissingDataProducers_MayConsume(t *testing.T) {
479487
wantErr bool
480488
}{
481489
{
482-
name: "MayConsume key with no producer — warning only, no error",
490+
name: "OptionalConsumes key with no producer — warning only, no error",
483491
existingPlugins: []fwkplugin.Plugin{
484492
&mockMayConsumerPlugin{
485-
name: "optional-consumer",
486-
mayConsume: map[fwkplugin.DataKey]any{keyA: nil},
493+
name: "optional-consumer",
494+
optionalConsumes: map[fwkplugin.DataKey]any{keyA: nil},
487495
},
488496
},
489497
factoryRegistry: map[string]fwkplugin.FactoryFunc{},
490498
wantErr: false, // must NOT error
491499
},
492500
{
493-
name: "MayConsume key with a producer present — no warning, no error",
501+
name: "OptionalConsumes key with a producer present — no warning, no error",
494502
existingPlugins: []fwkplugin.Plugin{
495503
&mockDataProducerP{name: "producer", produces: map[fwkplugin.DataKey]any{keyA: nil}},
496504
&mockMayConsumerPlugin{
497-
name: "optional-consumer",
498-
mayConsume: map[fwkplugin.DataKey]any{keyA: nil},
505+
name: "optional-consumer",
506+
optionalConsumes: map[fwkplugin.DataKey]any{keyA: nil},
499507
},
500508
},
501509
factoryRegistry: map[string]fwkplugin.FactoryFunc{producerTypeA: producerAFactory},
502510
wantErr: false,
503511
},
504512
{
505513
// Models the real prefix cache scorer — it requires prefix-match data (Consumes)
506-
// but optionally uses tokenized input (MayConsume), falling back to raw text.
514+
// but optionally uses tokenized input (OptionalConsumes), falling back to raw text.
507515
// The required key has a producer. The optional key does not.
508516
// Result: no error. Warning logged for the missing optional key.
509-
name: "plugin with both Consumes and MayConsume — required key has producer, optional does not",
517+
name: "plugin with both Consumes and OptionalConsumes — required key has producer, optional does not",
510518
existingPlugins: []fwkplugin.Plugin{
511519
&mockDataProducerP{name: "required-producer", produces: map[fwkplugin.DataKey]any{keyA: nil}},
512520
&mockMixedConsumerPlugin{
513-
name: "prefix-cache-scorer",
514-
consumes: map[fwkplugin.DataKey]any{keyA: nil},
515-
mayConsume: map[fwkplugin.DataKey]any{fwkplugin.NewDataKey("tokenized-input", "tokenizer"): nil},
521+
name: "prefix-cache-scorer",
522+
consumes: map[fwkplugin.DataKey]any{keyA: nil},
523+
optionalConsumes: map[fwkplugin.DataKey]any{fwkplugin.NewDataKey("tokenized-input", "tokenizer"): nil},
516524
},
517525
},
518526
factoryRegistry: map[string]fwkplugin.FactoryFunc{},

pkg/epp/framework/interface/plugin/plugins.go

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,11 @@ type ConsumerPlugin interface {
3030
// This is a map from DataKey produced to
3131
// the data type of the key (represented as data with default value casted as any field).
3232
Consumes() map[DataKey]any
33-
}
34-
35-
// MayConsumePlugin defines the interface for a plugin that optionally consumes data.
36-
// Unlike ConsumerPlugin, the framework will NOT error if no producer exists for these keys.
37-
// Instead it logs a warning at init time. The plugin must handle the case where this data is absent.
38-
type MayConsumePlugin interface {
39-
Plugin
40-
// MayConsume returns data keys the plugin can optionally consume.
41-
// The plugin must handle the case where this data is absent.
42-
MayConsume() map[DataKey]any
33+
// OptionalConsumes returns data keys the plugin can optionally consume.
34+
// Unlike Consumes(), the framework will NOT error if no producer exists for these keys.
35+
// Instead it logs a warning at init time. The plugin must handle the case where this data is absent.
36+
// Return nil if there are no optional keys.
37+
OptionalConsumes() map[DataKey]any
4338
}
4439

4540
// ProducerPlugin defines the interface for a producer.

pkg/epp/framework/interface/plugin/plugins_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ type consumerImpl struct {
3333
consumes map[DataKey]any
3434
}
3535

36-
func (c *consumerImpl) Consumes() map[DataKey]any { return c.consumes }
36+
func (c *consumerImpl) Consumes() map[DataKey]any { return c.consumes }
37+
func (c *consumerImpl) OptionalConsumes() map[DataKey]any { return nil }
3738

3839
type producerImpl struct {
3940
basePlugin

pkg/epp/framework/plugins/scheduling/scorer/activerequest/active_request.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ func (s *ActiveRequest) Consumes() map[plugin.DataKey]any {
149149
}
150150
}
151151

152+
// OptionalConsumes returns nil as this plugin has no optional data dependencies.
153+
func (s *ActiveRequest) OptionalConsumes() map[plugin.DataKey]any { return nil }
154+
152155
// Score scores the given endpoints based on the number of active requests
153156
// being served by each endpoint. The score is normalized to a range of 0-1.
154157
func (s *ActiveRequest) Score(ctx context.Context, _ *scheduling.InferenceRequest,

pkg/epp/framework/plugins/scheduling/scorer/mmcacheaffinity/scorer.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ func (s *Scorer) Consumes() map[plugin.DataKey]any {
8989
return map[plugin.DataKey]any{s.mmMatchDataKey: attrmm.EncoderCacheMatchInfo{}}
9090
}
9191

92+
// OptionalConsumes returns nil as this plugin has no optional data dependencies.
93+
func (s *Scorer) OptionalConsumes() map[plugin.DataKey]any { return nil }
94+
9295
// Score scores endpoints by matched multimodal encoder-cache item size divided
9396
// by total multimodal request item size.
9497
func (s *Scorer) Score(ctx context.Context, req *scheduling.InferenceRequest, endpoints []scheduling.Endpoint) map[scheduling.Endpoint]float64 {

pkg/epp/framework/plugins/scheduling/scorer/nohitlru/no_hit_lru.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ func (s *NoHitLRU) Consumes() map[plugin.DataKey]any {
128128
}
129129
}
130130

131+
// OptionalConsumes returns nil as this plugin has no optional data dependencies.
132+
func (s *NoHitLRU) OptionalConsumes() map[plugin.DataKey]any { return nil }
133+
131134
// isColdRequest determines if a request is cold by checking endpoint prefix-cache attributes.
132135
// Returns true when no endpoint reports any cache-hit blocks, or when no attribute is present.
133136
func (s *NoHitLRU) isColdRequest(ctx context.Context, endpoints []scheduling.Endpoint) bool {

0 commit comments

Comments
 (0)