@@ -19,6 +19,7 @@ package datastore
19
19
import (
20
20
"context"
21
21
"errors"
22
+ "fmt"
22
23
"math/rand"
23
24
"sync"
24
25
@@ -32,6 +33,10 @@ import (
32
33
logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
33
34
)
34
35
36
+ const (
37
+ ModelNameIndexKey = "spec.modelName"
38
+ )
39
+
35
40
var (
36
41
errPoolNotSynced = errors .New ("InferencePool is not initialized in data store" )
37
42
)
@@ -48,6 +53,7 @@ type Datastore interface {
48
53
ModelSetIfOlder (infModel * v1alpha2.InferenceModel ) bool
49
54
ModelGet (modelName string ) (* v1alpha2.InferenceModel , bool )
50
55
ModelDelete (namespacedName types.NamespacedName ) (* v1alpha2.InferenceModel , bool )
56
+ ModelResync (ctx context.Context , ctrlClient client.Client , modelName string ) (bool , error )
51
57
ModelGetAll () []* v1alpha2.InferenceModel
52
58
53
59
// PodMetrics operations
@@ -156,20 +162,53 @@ func (ds *datastore) ModelSetIfOlder(infModel *v1alpha2.InferenceModel) bool {
156
162
return false
157
163
}
158
164
}
159
- // Delete the model
160
- ds .modelDelete (types.NamespacedName {Name : infModel .Name , Namespace : infModel .Namespace })
165
+ // Set the model.
161
166
ds .models [infModel .Spec .ModelName ] = infModel
162
167
return true
163
168
}
164
169
170
+ func (ds * datastore ) ModelResync (ctx context.Context , c client.Client , modelName string ) (bool , error ) {
171
+ ds .poolAndModelsMu .Lock ()
172
+ defer ds .poolAndModelsMu .Unlock ()
173
+
174
+ var models v1alpha2.InferenceModelList
175
+ if err := c .List (ctx , & models , client.MatchingFields {ModelNameIndexKey : modelName }, client .InNamespace (ds .pool .Namespace )); err != nil {
176
+ return false , fmt .Errorf ("listing models that match the modelName %s: %w" , modelName , err )
177
+ }
178
+ if len (models .Items ) == 0 {
179
+ // No other instances of InferenceModels with this ModelName exists.
180
+ return false , nil
181
+ }
182
+
183
+ var oldest * v1alpha2.InferenceModel
184
+ for i := range models .Items {
185
+ m := & models .Items [i ]
186
+ if m .Spec .ModelName != modelName || // The index should filter those out, but just in case!
187
+ m .Spec .PoolRef .Name != ds .pool .Name || // We don't care about other pools, we could setup an index on this too!
188
+ ! m .DeletionTimestamp .IsZero () { // ignore objects marked for deletion
189
+ continue
190
+ }
191
+ if oldest == nil || m .ObjectMeta .CreationTimestamp .Before (& oldest .ObjectMeta .CreationTimestamp ) {
192
+ oldest = m
193
+ }
194
+ }
195
+ if oldest == nil {
196
+ return false , nil
197
+ }
198
+ ds .models [modelName ] = oldest
199
+ return true , nil
200
+ }
201
+
165
202
func (ds * datastore ) ModelGet (modelName string ) (* v1alpha2.InferenceModel , bool ) {
166
203
ds .poolAndModelsMu .RLock ()
167
204
defer ds .poolAndModelsMu .RUnlock ()
168
205
m , exists := ds .models [modelName ]
169
206
return m , exists
170
207
}
171
208
172
- func (ds * datastore ) modelDelete (namespacedName types.NamespacedName ) (* v1alpha2.InferenceModel , bool ) {
209
+ func (ds * datastore ) ModelDelete (namespacedName types.NamespacedName ) (* v1alpha2.InferenceModel , bool ) {
210
+ ds .poolAndModelsMu .Lock ()
211
+ defer ds .poolAndModelsMu .Unlock ()
173
212
for _ , m := range ds .models {
174
213
if m .Name == namespacedName .Name && m .Namespace == namespacedName .Namespace {
175
214
delete (ds .models , m .Spec .ModelName )
@@ -179,12 +218,6 @@ func (ds *datastore) modelDelete(namespacedName types.NamespacedName) (*v1alpha2
179
218
return nil , false
180
219
}
181
220
182
- func (ds * datastore ) ModelDelete (namespacedName types.NamespacedName ) (* v1alpha2.InferenceModel , bool ) {
183
- ds .poolAndModelsMu .Lock ()
184
- defer ds .poolAndModelsMu .Unlock ()
185
- return ds .modelDelete (namespacedName )
186
- }
187
-
188
221
func (ds * datastore ) ModelGetAll () []* v1alpha2.InferenceModel {
189
222
ds .poolAndModelsMu .RLock ()
190
223
defer ds .poolAndModelsMu .RUnlock ()
0 commit comments