@@ -20,8 +20,10 @@ import (
20
20
"encoding/json"
21
21
"fmt"
22
22
"net/url"
23
+ "runtime"
23
24
"strings"
24
25
"sync"
26
+ "time"
25
27
26
28
"github.com/confluentinc/confluent-kafka-go/v2/schemaregistry/cache"
27
29
)
@@ -189,6 +191,9 @@ type client struct {
189
191
schemaToVersionCacheLock sync.RWMutex
190
192
versionToSchemaCache cache.Cache
191
193
versionToSchemaCacheLock sync.RWMutex
194
+ latestToSchemaCache cache.Cache
195
+ latestToSchemaCacheLock sync.RWMutex
196
+ evictor * evictor
192
197
}
193
198
194
199
var _ Client = new (client )
@@ -243,6 +248,7 @@ func NewClient(conf *Config) (Client, error) {
243
248
var idToSchemaCache cache.Cache
244
249
var schemaToVersionCache cache.Cache
245
250
var versionToSchemaCache cache.Cache
251
+ var latestToSchemaCache cache.Cache
246
252
if conf .CacheCapacity != 0 {
247
253
schemaToIDCache , err = cache .NewLRUCache (conf .CacheCapacity )
248
254
if err != nil {
@@ -260,18 +266,28 @@ func NewClient(conf *Config) (Client, error) {
260
266
if err != nil {
261
267
return nil , err
262
268
}
269
+ latestToSchemaCache , err = cache .NewLRUCache (conf .CacheCapacity )
270
+ if err != nil {
271
+ return nil , err
272
+ }
263
273
} else {
264
274
schemaToIDCache = cache .NewMapCache ()
265
275
idToSchemaCache = cache .NewMapCache ()
266
276
schemaToVersionCache = cache .NewMapCache ()
267
277
versionToSchemaCache = cache .NewMapCache ()
278
+ latestToSchemaCache = cache .NewMapCache ()
268
279
}
269
280
handle := & client {
270
281
restService : restService ,
271
282
schemaToIDCache : schemaToIDCache ,
272
283
idToSchemaCache : idToSchemaCache ,
273
284
schemaToVersionCache : schemaToVersionCache ,
274
285
versionToSchemaCache : versionToSchemaCache ,
286
+ latestToSchemaCache : latestToSchemaCache ,
287
+ }
288
+ if conf .CacheLatestTTLSecs > 0 {
289
+ runEvictor (handle , time .Duration (conf .CacheLatestTTLSecs )* time .Second )
290
+ runtime .SetFinalizer (handle , stopEvictor )
275
291
}
276
292
return handle , nil
277
293
}
@@ -393,7 +409,26 @@ func (c *client) GetID(subject string, schema SchemaInfo, normalize bool) (id in
393
409
// GetLatestSchemaMetadata fetches latest version registered with the provided subject
394
410
// Returns SchemaMetadata object
395
411
func (c * client ) GetLatestSchemaMetadata (subject string ) (result SchemaMetadata , err error ) {
396
- return c .GetSchemaMetadata (subject , - 1 )
412
+ c .latestToSchemaCacheLock .RLock ()
413
+ metadataValue , ok := c .latestToSchemaCache .Get (subject )
414
+ c .latestToSchemaCacheLock .RUnlock ()
415
+ if ok {
416
+ return * metadataValue .(* SchemaMetadata ), nil
417
+ }
418
+
419
+ c .latestToSchemaCacheLock .Lock ()
420
+ // another goroutine could have already put it in cache
421
+ metadataValue , ok = c .latestToSchemaCache .Get (subject )
422
+ if ! ok {
423
+ err = c .restService .handleRequest (newRequest ("GET" , versions , nil , url .PathEscape (subject ), "latest" ), & result )
424
+ if err == nil {
425
+ c .latestToSchemaCache .Put (subject , & result )
426
+ }
427
+ } else {
428
+ result = * metadataValue .(* SchemaMetadata )
429
+ }
430
+ c .latestToSchemaCacheLock .Unlock ()
431
+ return result , err
397
432
}
398
433
399
434
// GetSchemaMetadata fetches the requested subject schema identified by version
@@ -687,3 +722,34 @@ func (c *client) UpdateDefaultCompatibility(update Compatibility) (compatibility
687
722
688
723
return result .CompatibilityUpdate , err
689
724
}
725
+
726
+ type evictor struct {
727
+ Interval time.Duration
728
+ stop chan bool
729
+ }
730
+
731
+ func (e * evictor ) Run (c cache.Cache ) {
732
+ ticker := time .NewTicker (e .Interval )
733
+ for {
734
+ select {
735
+ case <- ticker .C :
736
+ c .Clear ()
737
+ case <- e .stop :
738
+ ticker .Stop ()
739
+ return
740
+ }
741
+ }
742
+ }
743
+
744
+ func stopEvictor (c * client ) {
745
+ c .evictor .stop <- true
746
+ }
747
+
748
+ func runEvictor (c * client , ci time.Duration ) {
749
+ e := & evictor {
750
+ Interval : ci ,
751
+ stop : make (chan bool ),
752
+ }
753
+ c .evictor = e
754
+ go e .Run (c .latestToSchemaCache )
755
+ }
0 commit comments