From 5cc4303e2cedb5b07ccfde0459975aaf075180c3 Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Tue, 17 Jun 2025 18:26:48 -0400 Subject: [PATCH 1/8] ers initial cache setup, fix cache initialization --- service/entityresolution/entityresolution.go | 23 +++++++++++++++++-- .../keycloak/entity_resolution.go | 6 +++-- .../keycloak/v2/entity_resolution.go | 6 +++-- .../entityresolution/v2/entity_resolution.go | 18 +++++++++++++-- service/pkg/server/services.go | 13 ++++++----- .../pkg/serviceregistry/serviceregistry.go | 9 ++------ 6 files changed, 54 insertions(+), 21 deletions(-) diff --git a/service/entityresolution/entityresolution.go b/service/entityresolution/entityresolution.go index 38622f8b39..ecb6421bf3 100644 --- a/service/entityresolution/entityresolution.go +++ b/service/entityresolution/entityresolution.go @@ -1,17 +1,22 @@ package entityresolution import ( + "time" + "github.com/go-viper/mapstructure/v2" "github.com/opentdf/platform/protocol/go/entityresolution" "github.com/opentdf/platform/protocol/go/entityresolution/entityresolutionconnect" claims "github.com/opentdf/platform/service/entityresolution/claims" keycloak "github.com/opentdf/platform/service/entityresolution/keycloak" + "github.com/opentdf/platform/service/pkg/cache" "github.com/opentdf/platform/service/pkg/serviceregistry" "go.opentelemetry.io/otel/trace" ) type ERSConfig struct { - Mode string `mapstructure:"mode" json:"mode"` + Mode string `mapstructure:"mode" json:"mode"` + CacheExpiration string `mapstructure:"cacheexpiration" json:"cacheexpiration" default:"5m"` + CacheCost int `mapstructure:"cachecost" json:"cachecost" default:"100"` } const ( @@ -32,6 +37,7 @@ func NewRegistration() *serviceregistry.Service[entityresolutionconnect.EntityRe ConnectRPCFunc: entityresolutionconnect.NewEntityResolutionServiceHandler, GRPCGatewayFunc: entityresolution.RegisterEntityResolutionServiceHandler, RegisterFunc: func(srp serviceregistry.RegistrationParams) (entityresolutionconnect.EntityResolutionServiceHandler, serviceregistry.HandlerServer) { + srp.Logger.Info("Registering Entity Resolution Service") var inputConfig ERSConfig if err := mapstructure.Decode(srp.Config, &inputConfig); err != nil { @@ -42,9 +48,22 @@ func NewRegistration() *serviceregistry.Service[entityresolutionconnect.EntityRe claimsSVC.Tracer = srp.Tracer return EntityResolution{EntityResolutionServiceHandler: claimsSVC}, claimsHandler } + exp, err := time.ParseDuration(inputConfig.CacheExpiration) + if err != nil { + srp.Logger.Error("Failed to parse cache expiration duration", "error", err) + panic(err) + } + ersCache, err := srp.NewCacheFunc(cache.Options{ + Expiration: exp, + Cost: int64(inputConfig.CacheCost), + }) + if err != nil { + srp.Logger.Error("Failed to create cache for Entity Resolution Service", "error", err) + panic(err) + } // Default to keycloak ERS - kcSVC, kcHandler := keycloak.RegisterKeycloakERS(srp.Config, srp.Logger) + kcSVC, kcHandler := keycloak.RegisterKeycloakERS(srp.Config, srp.Logger, ersCache) kcSVC.Tracer = srp.Tracer return EntityResolution{EntityResolutionServiceHandler: kcSVC, Tracer: srp.Tracer}, kcHandler diff --git a/service/entityresolution/keycloak/entity_resolution.go b/service/entityresolution/keycloak/entity_resolution.go index 4d32e20d88..5616d70326 100644 --- a/service/entityresolution/keycloak/entity_resolution.go +++ b/service/entityresolution/keycloak/entity_resolution.go @@ -21,6 +21,7 @@ import ( "github.com/opentdf/platform/protocol/go/entityresolution" "github.com/opentdf/platform/service/entity" "github.com/opentdf/platform/service/logger" + "github.com/opentdf/platform/service/pkg/cache" "github.com/opentdf/platform/service/pkg/config" "github.com/opentdf/platform/service/pkg/serviceregistry" "go.opentelemetry.io/otel/trace" @@ -49,6 +50,7 @@ type KeycloakEntityResolutionService struct { //nolint:revive // Too late! Alrea trace.Tracer connector *KeyCloakConnector connectorMu sync.Mutex + svcCache *cache.Cache } type KeycloakConfig struct { //nolint:revive // yeah but what if we want to embed multiple configs? @@ -62,7 +64,7 @@ type KeycloakConfig struct { //nolint:revive // yeah but what if we want to embe TokenBuffer time.Duration `mapstructure:"token_buffer_seconds" json:"token_buffer_seconds" default:"120s"` } -func RegisterKeycloakERS(config config.ServiceConfig, logger *logger.Logger) (*KeycloakEntityResolutionService, serviceregistry.HandlerServer) { +func RegisterKeycloakERS(config config.ServiceConfig, logger *logger.Logger, svcCache *cache.Cache) (*KeycloakEntityResolutionService, serviceregistry.HandlerServer) { var inputIdpConfig KeycloakConfig if err := defaults.Set(&inputIdpConfig); err != nil { @@ -73,7 +75,7 @@ func RegisterKeycloakERS(config config.ServiceConfig, logger *logger.Logger) (*K panic(err) } logger.Debug("entity_resolution configuration", "config", inputIdpConfig) - keycloakSVC := &KeycloakEntityResolutionService{idpConfig: inputIdpConfig, logger: logger} + keycloakSVC := &KeycloakEntityResolutionService{idpConfig: inputIdpConfig, logger: logger, svcCache: svcCache} return keycloakSVC, nil } diff --git a/service/entityresolution/keycloak/v2/entity_resolution.go b/service/entityresolution/keycloak/v2/entity_resolution.go index a69d4449fd..5351d78f11 100644 --- a/service/entityresolution/keycloak/v2/entity_resolution.go +++ b/service/entityresolution/keycloak/v2/entity_resolution.go @@ -20,6 +20,7 @@ import ( entityresolutionV2 "github.com/opentdf/platform/protocol/go/entityresolution/v2" ent "github.com/opentdf/platform/service/entity" "github.com/opentdf/platform/service/logger" + "github.com/opentdf/platform/service/pkg/cache" "github.com/opentdf/platform/service/pkg/config" "github.com/opentdf/platform/service/pkg/serviceregistry" "go.opentelemetry.io/otel/trace" @@ -48,6 +49,7 @@ type EntityResolutionServiceV2 struct { trace.Tracer connector *Connector connectorMu sync.Mutex + svcCache *cache.Cache } type Config struct { @@ -61,7 +63,7 @@ type Config struct { TokenBuffer time.Duration `mapstructure:"token_buffer_seconds" json:"token_buffer_seconds" default:"120s"` } -func RegisterKeycloakERS(config config.ServiceConfig, logger *logger.Logger) (*EntityResolutionServiceV2, serviceregistry.HandlerServer) { +func RegisterKeycloakERS(config config.ServiceConfig, logger *logger.Logger, svcCache *cache.Cache) (*EntityResolutionServiceV2, serviceregistry.HandlerServer) { var inputIdpConfig Config if err := defaults.Set(&inputIdpConfig); err != nil { @@ -72,7 +74,7 @@ func RegisterKeycloakERS(config config.ServiceConfig, logger *logger.Logger) (*E panic(err) } logger.Debug("entity_resolution configuration", "config", inputIdpConfig) - keycloakSVC := &EntityResolutionServiceV2{idpConfig: inputIdpConfig, logger: logger} + keycloakSVC := &EntityResolutionServiceV2{idpConfig: inputIdpConfig, logger: logger, svcCache: svcCache} return keycloakSVC, nil } diff --git a/service/entityresolution/v2/entity_resolution.go b/service/entityresolution/v2/entity_resolution.go index 9fd485b2c0..2d9acdb567 100644 --- a/service/entityresolution/v2/entity_resolution.go +++ b/service/entityresolution/v2/entity_resolution.go @@ -1,17 +1,22 @@ package entityresolution import ( + "time" + "github.com/go-viper/mapstructure/v2" ersV2 "github.com/opentdf/platform/protocol/go/entityresolution/v2" "github.com/opentdf/platform/protocol/go/entityresolution/v2/entityresolutionv2connect" claims "github.com/opentdf/platform/service/entityresolution/claims/v2" keycloak "github.com/opentdf/platform/service/entityresolution/keycloak/v2" + "github.com/opentdf/platform/service/pkg/cache" "github.com/opentdf/platform/service/pkg/serviceregistry" "go.opentelemetry.io/otel/trace" ) type ERSConfig struct { - Mode string `mapstructure:"mode" json:"mode"` + Mode string `mapstructure:"mode" json:"mode"` + cacheExpiration time.Duration `mapstructure:"cache_expiration" json:"cache_expiration" default:"5m"` + cacheCost int64 `mapstructure:"cache_cost" json:"cache_cost" default:"100"` } const ( @@ -43,8 +48,17 @@ func NewRegistration() *serviceregistry.Service[entityresolutionv2connect.Entity return EntityResolution{EntityResolutionServiceHandler: claimsSVC}, claimsHandler } + ersCache, err := srp.NewCacheFunc(cache.Options{ + Expiration: inputConfig.cacheExpiration, + Cost: inputConfig.cacheCost, + }) + if err != nil { + srp.Logger.Error("Failed to create cache for Entity Resolution Service", "error", err) + panic(err) + } + // Default to keycloak ERS - kcSVC, kcHandler := keycloak.RegisterKeycloakERS(srp.Config, srp.Logger) + kcSVC, kcHandler := keycloak.RegisterKeycloakERS(srp.Config, srp.Logger, ersCache) kcSVC.Tracer = srp.Tracer return EntityResolution{EntityResolutionServiceHandler: kcSVC, Tracer: srp.Tracer}, kcHandler diff --git a/service/pkg/server/services.go b/service/pkg/server/services.go index cfa6426450..4575e80762 100644 --- a/service/pkg/server/services.go +++ b/service/pkg/server/services.go @@ -194,13 +194,14 @@ func startServices(ctx context.Context, params startServicesParams) (func(), err svcLogger = svcLogger.With("version", svc.GetVersion()) } - // Check if the service supports and needs a cache - var cacheClient *cache.Cache - if cacheSvc, ok := svc.(serviceregistry.CacheSupportedService); ok { - cacheClient, err = cacheManager.NewCache(ns, svcLogger, *cacheSvc.CacheOptions()) + // Function to create a cache given cache options + var createCacheClient func(cache.Options) (*cache.Cache, error) = func(options cache.Options) (*cache.Cache, error) { + slog.Info("creating cache client for", slog.String("namespace", ns), slog.String("service", svc.GetServiceDesc().ServiceName)) + cacheClient, err := cacheManager.NewCache(fmt.Sprintf("%s-%s", ns, svc.GetServiceDesc().ServiceName), svcLogger, options) if err != nil { - return func() {}, fmt.Errorf("issue creating cache client for %s: %w", ns, err) + return nil, fmt.Errorf("issue creating cache client for %s: %w", fmt.Sprintf("%s-%s", ns, svc.GetServiceDesc().ServiceName), err) } + return cacheClient, nil } err = svc.Start(ctx, serviceregistry.RegistrationParams{ @@ -212,7 +213,7 @@ func startServices(ctx context.Context, params startServicesParams) (func(), err RegisterReadinessCheck: health.RegisterReadinessCheck, OTDF: otdf, // TODO: REMOVE THIS Tracer: tracer, - Cache: cacheClient, + NewCacheFunc: createCacheClient, KeyManagers: keyManagers, }) if err != nil { diff --git a/service/pkg/serviceregistry/serviceregistry.go b/service/pkg/serviceregistry/serviceregistry.go index 2e24bcd63c..a6edfcf678 100644 --- a/service/pkg/serviceregistry/serviceregistry.go +++ b/service/pkg/serviceregistry/serviceregistry.go @@ -44,8 +44,8 @@ type RegistrationParams struct { Logger *logger.Logger trace.Tracer - // Cache is the cache that can be used to cache data. This cache is scoped to the service - Cache *cache.Cache + // NewCacheFunc is a function that can be used to create a new cache instance for the service + NewCacheFunc func(cache.Options) (*cache.Cache, error) KeyManagers []trust.KeyManager @@ -90,11 +90,6 @@ type IService interface { RegisterHTTPHandlers(context.Context, *runtime.ServeMux) error } -// CacheSupportedService is implemented by services that support caching. -type CacheSupportedService interface { - CacheOptions() *cache.Options -} - // Service is a struct that holds the registration information for a service as well as the state // of the service within the instance of the platform. type Service[S any] struct { From d6c67e91e42eb8dbc5b5cbe7b93facd03ffcf826 Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Wed, 18 Jun 2025 00:53:31 -0400 Subject: [PATCH 2/8] fix v2 --- service/entityresolution/v2/entity_resolution.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/service/entityresolution/v2/entity_resolution.go b/service/entityresolution/v2/entity_resolution.go index 2d9acdb567..895fec7c08 100644 --- a/service/entityresolution/v2/entity_resolution.go +++ b/service/entityresolution/v2/entity_resolution.go @@ -14,9 +14,9 @@ import ( ) type ERSConfig struct { - Mode string `mapstructure:"mode" json:"mode"` - cacheExpiration time.Duration `mapstructure:"cache_expiration" json:"cache_expiration" default:"5m"` - cacheCost int64 `mapstructure:"cache_cost" json:"cache_cost" default:"100"` + Mode string `mapstructure:"mode" json:"mode"` + CacheExpiration string `mapstructure:"cache_expiration" json:"cache_expiration" default:"5m"` + CacheCost int `mapstructure:"cache_cost" json:"cache_cost" default:"100"` } const ( @@ -47,10 +47,14 @@ func NewRegistration() *serviceregistry.Service[entityresolutionv2connect.Entity claimsSVC.Tracer = srp.Tracer return EntityResolution{EntityResolutionServiceHandler: claimsSVC}, claimsHandler } - + exp, err := time.ParseDuration(inputConfig.CacheExpiration) + if err != nil { + srp.Logger.Error("Failed to parse cache expiration duration", "error", err) + panic(err) + } ersCache, err := srp.NewCacheFunc(cache.Options{ - Expiration: inputConfig.cacheExpiration, - Cost: inputConfig.cacheCost, + Expiration: exp, + Cost: int64(inputConfig.CacheCost), }) if err != nil { srp.Logger.Error("Failed to create cache for Entity Resolution Service", "error", err) From ec7c44d97d614a259a4ddb2f4351c82167559f8e Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Wed, 18 Jun 2025 01:04:44 -0400 Subject: [PATCH 3/8] fix defaults --- service/entityresolution/entityresolution.go | 12 +++++++++--- service/entityresolution/v2/entity_resolution.go | 10 ++++++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/service/entityresolution/entityresolution.go b/service/entityresolution/entityresolution.go index ecb6421bf3..f9aafeea0f 100644 --- a/service/entityresolution/entityresolution.go +++ b/service/entityresolution/entityresolution.go @@ -15,8 +15,8 @@ import ( type ERSConfig struct { Mode string `mapstructure:"mode" json:"mode"` - CacheExpiration string `mapstructure:"cacheexpiration" json:"cacheexpiration" default:"5m"` - CacheCost int `mapstructure:"cachecost" json:"cachecost" default:"100"` + CacheExpiration string `mapstructure:"cacheexpiration" json:"cacheexpiration"` + CacheCost int64 `mapstructure:"cachecost" json:"cachecost"` } const ( @@ -48,6 +48,12 @@ func NewRegistration() *serviceregistry.Service[entityresolutionconnect.EntityRe claimsSVC.Tracer = srp.Tracer return EntityResolution{EntityResolutionServiceHandler: claimsSVC}, claimsHandler } + if inputConfig.CacheExpiration == "" { + inputConfig.CacheExpiration = "5m" // Default cache expiration + } + if inputConfig.CacheCost == 0 { + inputConfig.CacheCost = 100 // Default cache cost + } exp, err := time.ParseDuration(inputConfig.CacheExpiration) if err != nil { srp.Logger.Error("Failed to parse cache expiration duration", "error", err) @@ -55,7 +61,7 @@ func NewRegistration() *serviceregistry.Service[entityresolutionconnect.EntityRe } ersCache, err := srp.NewCacheFunc(cache.Options{ Expiration: exp, - Cost: int64(inputConfig.CacheCost), + Cost: inputConfig.CacheCost, }) if err != nil { srp.Logger.Error("Failed to create cache for Entity Resolution Service", "error", err) diff --git a/service/entityresolution/v2/entity_resolution.go b/service/entityresolution/v2/entity_resolution.go index 895fec7c08..7d7801bb90 100644 --- a/service/entityresolution/v2/entity_resolution.go +++ b/service/entityresolution/v2/entity_resolution.go @@ -15,8 +15,8 @@ import ( type ERSConfig struct { Mode string `mapstructure:"mode" json:"mode"` - CacheExpiration string `mapstructure:"cache_expiration" json:"cache_expiration" default:"5m"` - CacheCost int `mapstructure:"cache_cost" json:"cache_cost" default:"100"` + CacheExpiration string `mapstructure:"cache_expiration" json:"cache_expiration"` + CacheCost int `mapstructure:"cache_cost" json:"cache_cost"` } const ( @@ -47,6 +47,12 @@ func NewRegistration() *serviceregistry.Service[entityresolutionv2connect.Entity claimsSVC.Tracer = srp.Tracer return EntityResolution{EntityResolutionServiceHandler: claimsSVC}, claimsHandler } + if inputConfig.CacheExpiration == "" { + inputConfig.CacheExpiration = "5m" // Default cache expiration + } + if inputConfig.CacheCost == 0 { + inputConfig.CacheCost = 100 // Default cache cost + } exp, err := time.ParseDuration(inputConfig.CacheExpiration) if err != nil { srp.Logger.Error("Failed to parse cache expiration duration", "error", err) From 051529b35cb961e7178e2c15caa517a99e8cba13 Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Wed, 18 Jun 2025 12:45:22 -0400 Subject: [PATCH 4/8] suggested edits --- service/entityresolution/entityresolution.go | 6 +++--- service/entityresolution/v2/entity_resolution.go | 2 +- service/pkg/cache/cache.go | 10 ++++++---- service/pkg/server/services.go | 6 +++--- service/pkg/serviceregistry/serviceregistry.go | 4 ++-- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/service/entityresolution/entityresolution.go b/service/entityresolution/entityresolution.go index f9aafeea0f..e34a18d3a1 100644 --- a/service/entityresolution/entityresolution.go +++ b/service/entityresolution/entityresolution.go @@ -15,8 +15,8 @@ import ( type ERSConfig struct { Mode string `mapstructure:"mode" json:"mode"` - CacheExpiration string `mapstructure:"cacheexpiration" json:"cacheexpiration"` - CacheCost int64 `mapstructure:"cachecost" json:"cachecost"` + CacheExpiration string `mapstructure:"cache_expiration" json:"cache_expiration"` + CacheCost int64 `mapstructure:"cache_cost" json:"cache_cost"` } const ( @@ -59,7 +59,7 @@ func NewRegistration() *serviceregistry.Service[entityresolutionconnect.EntityRe srp.Logger.Error("Failed to parse cache expiration duration", "error", err) panic(err) } - ersCache, err := srp.NewCacheFunc(cache.Options{ + ersCache, err := srp.NewCacheClient(cache.Options{ Expiration: exp, Cost: inputConfig.CacheCost, }) diff --git a/service/entityresolution/v2/entity_resolution.go b/service/entityresolution/v2/entity_resolution.go index 7d7801bb90..4424caddfe 100644 --- a/service/entityresolution/v2/entity_resolution.go +++ b/service/entityresolution/v2/entity_resolution.go @@ -58,7 +58,7 @@ func NewRegistration() *serviceregistry.Service[entityresolutionv2connect.Entity srp.Logger.Error("Failed to parse cache expiration duration", "error", err) panic(err) } - ersCache, err := srp.NewCacheFunc(cache.Options{ + ersCache, err := srp.NewCacheClient(cache.Options{ Expiration: exp, Cost: int64(inputConfig.CacheCost), }) diff --git a/service/pkg/cache/cache.go b/service/pkg/cache/cache.go index b9927e182f..916c2319c8 100644 --- a/service/pkg/cache/cache.go +++ b/service/pkg/cache/cache.go @@ -91,10 +91,12 @@ func (c *Cache) Get(ctx context.Context, key string) (any, error) { // Set stores a value of type T in the cache. func (c *Cache) Set(ctx context.Context, key string, object any, tags []string) error { tags = append(tags, c.getServiceTag()) - opts := []store.Option{ - store.WithTags(tags), - store.WithExpiration(c.cacheOptions.Expiration), - store.WithCost(c.cacheOptions.Cost), + opts := []store.Option{store.WithTags(tags)} + if c.cacheOptions.Expiration > 0 { + opts = append(opts, store.WithExpiration(c.cacheOptions.Expiration)) + } + if c.cacheOptions.Cost > 0 { + opts = append(opts, store.WithCost(c.cacheOptions.Cost)) } err := c.manager.cache.Set(ctx, c.getKey(key), object, opts...) diff --git a/service/pkg/server/services.go b/service/pkg/server/services.go index 4575e80762..2e67a5d573 100644 --- a/service/pkg/server/services.go +++ b/service/pkg/server/services.go @@ -197,9 +197,9 @@ func startServices(ctx context.Context, params startServicesParams) (func(), err // Function to create a cache given cache options var createCacheClient func(cache.Options) (*cache.Cache, error) = func(options cache.Options) (*cache.Cache, error) { slog.Info("creating cache client for", slog.String("namespace", ns), slog.String("service", svc.GetServiceDesc().ServiceName)) - cacheClient, err := cacheManager.NewCache(fmt.Sprintf("%s-%s", ns, svc.GetServiceDesc().ServiceName), svcLogger, options) + cacheClient, err := cacheManager.NewCache(ns, svcLogger, options) if err != nil { - return nil, fmt.Errorf("issue creating cache client for %s: %w", fmt.Sprintf("%s-%s", ns, svc.GetServiceDesc().ServiceName), err) + return nil, fmt.Errorf("issue creating cache client for %s: %w", ns, err) } return cacheClient, nil } @@ -213,7 +213,7 @@ func startServices(ctx context.Context, params startServicesParams) (func(), err RegisterReadinessCheck: health.RegisterReadinessCheck, OTDF: otdf, // TODO: REMOVE THIS Tracer: tracer, - NewCacheFunc: createCacheClient, + NewCacheClient: createCacheClient, KeyManagers: keyManagers, }) if err != nil { diff --git a/service/pkg/serviceregistry/serviceregistry.go b/service/pkg/serviceregistry/serviceregistry.go index a6edfcf678..701ab0ba65 100644 --- a/service/pkg/serviceregistry/serviceregistry.go +++ b/service/pkg/serviceregistry/serviceregistry.go @@ -44,8 +44,8 @@ type RegistrationParams struct { Logger *logger.Logger trace.Tracer - // NewCacheFunc is a function that can be used to create a new cache instance for the service - NewCacheFunc func(cache.Options) (*cache.Cache, error) + // NewCacheClient is a function that can be used to create a new cache instance for the service + NewCacheClient func(cache.Options) (*cache.Cache, error) KeyManagers []trust.KeyManager From 563779bbe194b19c1cd60897e8c6e7cfcd66f422 Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Wed, 18 Jun 2025 12:50:18 -0400 Subject: [PATCH 5/8] default to no caching if exp isnt set --- service/entityresolution/entityresolution.go | 37 ++++++++--------- .../entityresolution/v2/entity_resolution.go | 40 ++++++++++--------- service/pkg/cache/cache.go | 3 -- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/service/entityresolution/entityresolution.go b/service/entityresolution/entityresolution.go index e34a18d3a1..f1113456eb 100644 --- a/service/entityresolution/entityresolution.go +++ b/service/entityresolution/entityresolution.go @@ -48,24 +48,25 @@ func NewRegistration() *serviceregistry.Service[entityresolutionconnect.EntityRe claimsSVC.Tracer = srp.Tracer return EntityResolution{EntityResolutionServiceHandler: claimsSVC}, claimsHandler } - if inputConfig.CacheExpiration == "" { - inputConfig.CacheExpiration = "5m" // Default cache expiration - } - if inputConfig.CacheCost == 0 { - inputConfig.CacheCost = 100 // Default cache cost - } - exp, err := time.ParseDuration(inputConfig.CacheExpiration) - if err != nil { - srp.Logger.Error("Failed to parse cache expiration duration", "error", err) - panic(err) - } - ersCache, err := srp.NewCacheClient(cache.Options{ - Expiration: exp, - Cost: inputConfig.CacheCost, - }) - if err != nil { - srp.Logger.Error("Failed to create cache for Entity Resolution Service", "error", err) - panic(err) + var ersCache *cache.Cache + // default to no cache if no exipiration is set + if inputConfig.CacheExpiration != "" { + if inputConfig.CacheCost == 0 { + inputConfig.CacheCost = 100 // Default cache cost + } + exp, err := time.ParseDuration(inputConfig.CacheExpiration) + if err != nil { + srp.Logger.Error("Failed to parse cache expiration duration", "error", err) + panic(err) + } + ersCache, err = srp.NewCacheClient(cache.Options{ + Expiration: exp, + Cost: inputConfig.CacheCost, + }) + if err != nil { + srp.Logger.Error("Failed to create cache for Entity Resolution Service", "error", err) + panic(err) + } } // Default to keycloak ERS diff --git a/service/entityresolution/v2/entity_resolution.go b/service/entityresolution/v2/entity_resolution.go index 4424caddfe..ff9c77d3d8 100644 --- a/service/entityresolution/v2/entity_resolution.go +++ b/service/entityresolution/v2/entity_resolution.go @@ -16,7 +16,7 @@ import ( type ERSConfig struct { Mode string `mapstructure:"mode" json:"mode"` CacheExpiration string `mapstructure:"cache_expiration" json:"cache_expiration"` - CacheCost int `mapstructure:"cache_cost" json:"cache_cost"` + CacheCost int64 `mapstructure:"cache_cost" json:"cache_cost"` } const ( @@ -47,24 +47,26 @@ func NewRegistration() *serviceregistry.Service[entityresolutionv2connect.Entity claimsSVC.Tracer = srp.Tracer return EntityResolution{EntityResolutionServiceHandler: claimsSVC}, claimsHandler } - if inputConfig.CacheExpiration == "" { - inputConfig.CacheExpiration = "5m" // Default cache expiration - } - if inputConfig.CacheCost == 0 { - inputConfig.CacheCost = 100 // Default cache cost - } - exp, err := time.ParseDuration(inputConfig.CacheExpiration) - if err != nil { - srp.Logger.Error("Failed to parse cache expiration duration", "error", err) - panic(err) - } - ersCache, err := srp.NewCacheClient(cache.Options{ - Expiration: exp, - Cost: int64(inputConfig.CacheCost), - }) - if err != nil { - srp.Logger.Error("Failed to create cache for Entity Resolution Service", "error", err) - panic(err) + + var ersCache *cache.Cache + // default to no cache if no exipiration is set + if inputConfig.CacheExpiration != "" { + if inputConfig.CacheCost == 0 { + inputConfig.CacheCost = 100 // Default cache cost + } + exp, err := time.ParseDuration(inputConfig.CacheExpiration) + if err != nil { + srp.Logger.Error("Failed to parse cache expiration duration", "error", err) + panic(err) + } + ersCache, err = srp.NewCacheClient(cache.Options{ + Expiration: exp, + Cost: inputConfig.CacheCost, + }) + if err != nil { + srp.Logger.Error("Failed to create cache for Entity Resolution Service", "error", err) + panic(err) + } } // Default to keycloak ERS diff --git a/service/pkg/cache/cache.go b/service/pkg/cache/cache.go index 916c2319c8..29ac294889 100644 --- a/service/pkg/cache/cache.go +++ b/service/pkg/cache/cache.go @@ -92,9 +92,6 @@ func (c *Cache) Get(ctx context.Context, key string) (any, error) { func (c *Cache) Set(ctx context.Context, key string, object any, tags []string) error { tags = append(tags, c.getServiceTag()) opts := []store.Option{store.WithTags(tags)} - if c.cacheOptions.Expiration > 0 { - opts = append(opts, store.WithExpiration(c.cacheOptions.Expiration)) - } if c.cacheOptions.Cost > 0 { opts = append(opts, store.WithCost(c.cacheOptions.Cost)) } From add32667e194377e053dbec8881e2c2a1aa8653d Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Wed, 18 Jun 2025 12:56:19 -0400 Subject: [PATCH 6/8] remove cost from options --- service/entityresolution/entityresolution.go | 5 ----- service/entityresolution/v2/entity_resolution.go | 5 ----- service/pkg/cache/cache.go | 10 ++-------- service/pkg/cache/cache_test.go | 1 - 4 files changed, 2 insertions(+), 19 deletions(-) diff --git a/service/entityresolution/entityresolution.go b/service/entityresolution/entityresolution.go index f1113456eb..4162f2b1b7 100644 --- a/service/entityresolution/entityresolution.go +++ b/service/entityresolution/entityresolution.go @@ -16,7 +16,6 @@ import ( type ERSConfig struct { Mode string `mapstructure:"mode" json:"mode"` CacheExpiration string `mapstructure:"cache_expiration" json:"cache_expiration"` - CacheCost int64 `mapstructure:"cache_cost" json:"cache_cost"` } const ( @@ -51,9 +50,6 @@ func NewRegistration() *serviceregistry.Service[entityresolutionconnect.EntityRe var ersCache *cache.Cache // default to no cache if no exipiration is set if inputConfig.CacheExpiration != "" { - if inputConfig.CacheCost == 0 { - inputConfig.CacheCost = 100 // Default cache cost - } exp, err := time.ParseDuration(inputConfig.CacheExpiration) if err != nil { srp.Logger.Error("Failed to parse cache expiration duration", "error", err) @@ -61,7 +57,6 @@ func NewRegistration() *serviceregistry.Service[entityresolutionconnect.EntityRe } ersCache, err = srp.NewCacheClient(cache.Options{ Expiration: exp, - Cost: inputConfig.CacheCost, }) if err != nil { srp.Logger.Error("Failed to create cache for Entity Resolution Service", "error", err) diff --git a/service/entityresolution/v2/entity_resolution.go b/service/entityresolution/v2/entity_resolution.go index ff9c77d3d8..ac2cd15cef 100644 --- a/service/entityresolution/v2/entity_resolution.go +++ b/service/entityresolution/v2/entity_resolution.go @@ -16,7 +16,6 @@ import ( type ERSConfig struct { Mode string `mapstructure:"mode" json:"mode"` CacheExpiration string `mapstructure:"cache_expiration" json:"cache_expiration"` - CacheCost int64 `mapstructure:"cache_cost" json:"cache_cost"` } const ( @@ -51,9 +50,6 @@ func NewRegistration() *serviceregistry.Service[entityresolutionv2connect.Entity var ersCache *cache.Cache // default to no cache if no exipiration is set if inputConfig.CacheExpiration != "" { - if inputConfig.CacheCost == 0 { - inputConfig.CacheCost = 100 // Default cache cost - } exp, err := time.ParseDuration(inputConfig.CacheExpiration) if err != nil { srp.Logger.Error("Failed to parse cache expiration duration", "error", err) @@ -61,7 +57,6 @@ func NewRegistration() *serviceregistry.Service[entityresolutionv2connect.Entity } ersCache, err = srp.NewCacheClient(cache.Options{ Expiration: exp, - Cost: inputConfig.CacheCost, }) if err != nil { srp.Logger.Error("Failed to create cache for Entity Resolution Service", "error", err) diff --git a/service/pkg/cache/cache.go b/service/pkg/cache/cache.go index 29ac294889..3c99d7f33b 100644 --- a/service/pkg/cache/cache.go +++ b/service/pkg/cache/cache.go @@ -3,7 +3,6 @@ package cache import ( "context" "errors" - "strconv" "time" "github.com/dgraph-io/ristretto" @@ -30,7 +29,6 @@ type Cache struct { type Options struct { Expiration time.Duration - Cost int64 } // NewCacheManager creates a new cache manager using Ristretto as the backend. @@ -41,7 +39,7 @@ func NewCacheManager(maxCost int64) (*Manager, error) { } config := &ristretto.Config{ NumCounters: numCounters, // number of keys to track frequency of (10x max items) - MaxCost: maxCost, // maximum cost of cache (e.g., 1<<20 for 1MB) + // MaxCost: maxCost, // maximum cost of cache (e.g., 1<<20 for 1MB) BufferItems: bufferItems, // number of keys per Get buffer. } store, err := ristretto.NewCache(config) @@ -70,8 +68,7 @@ func (c *Manager) NewCache(serviceName string, log *logger.Logger, options Optio cache.logger = log. With("subsystem", "cache"). With("serviceTag", cache.getServiceTag()). - With("expiration", options.Expiration.String()). - With("cost", strconv.FormatInt(options.Cost, 10)) + With("expiration", options.Expiration.String()) cache.logger.Info("created cache") return cache, nil } @@ -92,9 +89,6 @@ func (c *Cache) Get(ctx context.Context, key string) (any, error) { func (c *Cache) Set(ctx context.Context, key string, object any, tags []string) error { tags = append(tags, c.getServiceTag()) opts := []store.Option{store.WithTags(tags)} - if c.cacheOptions.Cost > 0 { - opts = append(opts, store.WithCost(c.cacheOptions.Cost)) - } err := c.manager.cache.Set(ctx, c.getKey(key), object, opts...) if err != nil { diff --git a/service/pkg/cache/cache_test.go b/service/pkg/cache/cache_test.go index 552c94602d..efdfb517fb 100644 --- a/service/pkg/cache/cache_test.go +++ b/service/pkg/cache/cache_test.go @@ -36,7 +36,6 @@ func TestNewCacheManager_NewCacheIntegration(t *testing.T) { options := Options{ Expiration: 1 * time.Minute, - Cost: 1, } cache, err := manager.NewCache("testService", log, options) require.NoError(t, err) From fbd345d938ff204240f51338d374b55b1362793c Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Wed, 18 Jun 2025 12:57:52 -0400 Subject: [PATCH 7/8] fix cache, add todo --- service/pkg/cache/cache.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/service/pkg/cache/cache.go b/service/pkg/cache/cache.go index 3c99d7f33b..7cc70d9e76 100644 --- a/service/pkg/cache/cache.go +++ b/service/pkg/cache/cache.go @@ -29,6 +29,7 @@ type Cache struct { type Options struct { Expiration time.Duration + // Cost int64 // TODO } // NewCacheManager creates a new cache manager using Ristretto as the backend. @@ -39,7 +40,7 @@ func NewCacheManager(maxCost int64) (*Manager, error) { } config := &ristretto.Config{ NumCounters: numCounters, // number of keys to track frequency of (10x max items) - // MaxCost: maxCost, // maximum cost of cache (e.g., 1<<20 for 1MB) + MaxCost: maxCost, // maximum cost of cache (e.g., 1<<20 for 1MB) BufferItems: bufferItems, // number of keys per Get buffer. } store, err := ristretto.NewCache(config) @@ -89,6 +90,9 @@ func (c *Cache) Get(ctx context.Context, key string) (any, error) { func (c *Cache) Set(ctx context.Context, key string, object any, tags []string) error { tags = append(tags, c.getServiceTag()) opts := []store.Option{store.WithTags(tags)} + if c.cacheOptions.Expiration > 0 { + opts = append(opts, store.WithExpiration(c.cacheOptions.Expiration)) + } err := c.manager.cache.Set(ctx, c.getKey(key), object, opts...) if err != nil { From fcdef8161c637f7d99e65eec8c8a0e785c97922e Mon Sep 17 00:00:00 2001 From: Elizabeth Healy Date: Wed, 18 Jun 2025 12:58:41 -0400 Subject: [PATCH 8/8] remove log --- service/entityresolution/entityresolution.go | 1 - 1 file changed, 1 deletion(-) diff --git a/service/entityresolution/entityresolution.go b/service/entityresolution/entityresolution.go index 4162f2b1b7..defdfdaa93 100644 --- a/service/entityresolution/entityresolution.go +++ b/service/entityresolution/entityresolution.go @@ -36,7 +36,6 @@ func NewRegistration() *serviceregistry.Service[entityresolutionconnect.EntityRe ConnectRPCFunc: entityresolutionconnect.NewEntityResolutionServiceHandler, GRPCGatewayFunc: entityresolution.RegisterEntityResolutionServiceHandler, RegisterFunc: func(srp serviceregistry.RegistrationParams) (entityresolutionconnect.EntityResolutionServiceHandler, serviceregistry.HandlerServer) { - srp.Logger.Info("Registering Entity Resolution Service") var inputConfig ERSConfig if err := mapstructure.Decode(srp.Config, &inputConfig); err != nil {