Zanzana: Add more openfga settings for fine tuning (#115928)

* Zanzana: Add more openfga settings for fine tuning

* neat

* refactor
This commit is contained in:
Alexander Zobnin
2026-01-07 13:07:13 +01:00
committed by GitHub
parent 20eeff3e7b
commit 0b9046be15
2 changed files with 274 additions and 1 deletions
@@ -32,6 +32,8 @@ func NewOpenFGAServer(cfg setting.ZanzanaServerSettings, store storage.OpenFGADa
opts := []server.OpenFGAServiceV1Option{
server.WithDatastore(store),
server.WithLogger(zlogger.New(logger)),
// Cache settings
server.WithCheckCacheLimit(cfg.CacheSettings.CheckCacheLimit),
server.WithCacheControllerEnabled(cfg.CacheSettings.CacheControllerEnabled),
server.WithCacheControllerTTL(cfg.CacheSettings.CacheControllerTTL),
@@ -40,16 +42,25 @@ func NewOpenFGAServer(cfg setting.ZanzanaServerSettings, store storage.OpenFGADa
server.WithCheckIteratorCacheEnabled(cfg.CacheSettings.CheckIteratorCacheEnabled),
server.WithCheckIteratorCacheMaxResults(cfg.CacheSettings.CheckIteratorCacheMaxResults),
server.WithCheckIteratorCacheTTL(cfg.CacheSettings.CheckIteratorCacheTTL),
// ListObjects settings
server.WithListObjectsMaxResults(cfg.ListObjectsMaxResults),
server.WithListObjectsIteratorCacheEnabled(cfg.CacheSettings.ListObjectsIteratorCacheEnabled),
server.WithListObjectsIteratorCacheMaxResults(cfg.CacheSettings.ListObjectsIteratorCacheMaxResults),
server.WithListObjectsIteratorCacheTTL(cfg.CacheSettings.ListObjectsIteratorCacheTTL),
server.WithListObjectsDeadline(cfg.ListObjectsDeadline),
// Shared iterator settings
server.WithSharedIteratorEnabled(cfg.CacheSettings.SharedIteratorEnabled),
server.WithSharedIteratorLimit(cfg.CacheSettings.SharedIteratorLimit),
server.WithSharedIteratorTTL(cfg.CacheSettings.SharedIteratorTTL),
server.WithListObjectsDeadline(cfg.ListObjectsDeadline),
server.WithContextPropagationToDatastore(true),
}
openfgaOpts := withOpenFGAOptions(cfg)
opts = append(opts, openfgaOpts...)
srv, err := server.NewServerWithOpts(opts...)
if err != nil {
return nil, err
@@ -58,6 +69,129 @@ func NewOpenFGAServer(cfg setting.ZanzanaServerSettings, store storage.OpenFGADa
return srv, nil
}
func withOpenFGAOptions(cfg setting.ZanzanaServerSettings) []server.OpenFGAServiceV1Option {
opts := make([]server.OpenFGAServiceV1Option, 0)
listOpts := withListOptions(cfg)
opts = append(opts, listOpts...)
// Check settings
if cfg.OpenFgaServerSettings.MaxConcurrentReadsForCheck != 0 {
opts = append(opts, server.WithMaxConcurrentReadsForCheck(cfg.OpenFgaServerSettings.MaxConcurrentReadsForCheck))
}
if cfg.OpenFgaServerSettings.CheckDatabaseThrottleThreshold != 0 || cfg.OpenFgaServerSettings.CheckDatabaseThrottleDuration != 0 {
opts = append(opts, server.WithCheckDatabaseThrottle(cfg.OpenFgaServerSettings.CheckDatabaseThrottleThreshold, cfg.OpenFgaServerSettings.CheckDatabaseThrottleDuration))
}
// Batch check settings
if cfg.OpenFgaServerSettings.MaxConcurrentChecksPerBatchCheck != 0 {
opts = append(opts, server.WithMaxConcurrentChecksPerBatchCheck(cfg.OpenFgaServerSettings.MaxConcurrentChecksPerBatchCheck))
}
if cfg.OpenFgaServerSettings.MaxChecksPerBatchCheck != 0 {
opts = append(opts, server.WithMaxChecksPerBatchCheck(cfg.OpenFgaServerSettings.MaxChecksPerBatchCheck))
}
// Resolve node settings
if cfg.OpenFgaServerSettings.ResolveNodeLimit != 0 {
opts = append(opts, server.WithResolveNodeLimit(cfg.OpenFgaServerSettings.ResolveNodeLimit))
}
if cfg.OpenFgaServerSettings.ResolveNodeBreadthLimit != 0 {
opts = append(opts, server.WithResolveNodeBreadthLimit(cfg.OpenFgaServerSettings.ResolveNodeBreadthLimit))
}
// Dispatch throttling settings
if cfg.OpenFgaServerSettings.DispatchThrottlingCheckResolverEnabled {
opts = append(opts, server.WithDispatchThrottlingCheckResolverEnabled(cfg.OpenFgaServerSettings.DispatchThrottlingCheckResolverEnabled))
}
if cfg.OpenFgaServerSettings.DispatchThrottlingCheckResolverFrequency != 0 {
opts = append(opts, server.WithDispatchThrottlingCheckResolverFrequency(cfg.OpenFgaServerSettings.DispatchThrottlingCheckResolverFrequency))
}
if cfg.OpenFgaServerSettings.DispatchThrottlingCheckResolverThreshold != 0 {
opts = append(opts, server.WithDispatchThrottlingCheckResolverThreshold(cfg.OpenFgaServerSettings.DispatchThrottlingCheckResolverThreshold))
}
if cfg.OpenFgaServerSettings.DispatchThrottlingCheckResolverMaxThreshold != 0 {
opts = append(opts, server.WithDispatchThrottlingCheckResolverMaxThreshold(cfg.OpenFgaServerSettings.DispatchThrottlingCheckResolverMaxThreshold))
}
// Shadow check/query settings
if cfg.OpenFgaServerSettings.ShadowCheckResolverTimeout != 0 {
opts = append(opts, server.WithShadowCheckResolverTimeout(cfg.OpenFgaServerSettings.ShadowCheckResolverTimeout))
}
if cfg.OpenFgaServerSettings.ShadowListObjectsQueryTimeout != 0 {
opts = append(opts, server.WithShadowListObjectsQueryTimeout(cfg.OpenFgaServerSettings.ShadowListObjectsQueryTimeout))
}
if cfg.OpenFgaServerSettings.ShadowListObjectsQueryMaxDeltaItems != 0 {
opts = append(opts, server.WithShadowListObjectsQueryMaxDeltaItems(cfg.OpenFgaServerSettings.ShadowListObjectsQueryMaxDeltaItems))
}
if cfg.OpenFgaServerSettings.RequestTimeout != 0 {
opts = append(opts, server.WithRequestTimeout(cfg.OpenFgaServerSettings.RequestTimeout))
}
if cfg.OpenFgaServerSettings.MaxAuthorizationModelSizeInBytes != 0 {
opts = append(opts, server.WithMaxAuthorizationModelSizeInBytes(cfg.OpenFgaServerSettings.MaxAuthorizationModelSizeInBytes))
}
if cfg.OpenFgaServerSettings.AuthorizationModelCacheSize != 0 {
opts = append(opts, server.WithAuthorizationModelCacheSize(cfg.OpenFgaServerSettings.AuthorizationModelCacheSize))
}
if cfg.OpenFgaServerSettings.ChangelogHorizonOffset != 0 {
opts = append(opts, server.WithChangelogHorizonOffset(cfg.OpenFgaServerSettings.ChangelogHorizonOffset))
}
return opts
}
func withListOptions(cfg setting.ZanzanaServerSettings) []server.OpenFGAServiceV1Option {
opts := make([]server.OpenFGAServiceV1Option, 0)
// ListObjects settings
if cfg.OpenFgaServerSettings.MaxConcurrentReadsForListObjects != 0 {
opts = append(opts, server.WithMaxConcurrentReadsForListObjects(cfg.OpenFgaServerSettings.MaxConcurrentReadsForListObjects))
}
if cfg.OpenFgaServerSettings.ListObjectsDispatchThrottlingEnabled {
opts = append(opts, server.WithListObjectsDispatchThrottlingEnabled(cfg.OpenFgaServerSettings.ListObjectsDispatchThrottlingEnabled))
}
if cfg.OpenFgaServerSettings.ListObjectsDispatchThrottlingFrequency != 0 {
opts = append(opts, server.WithListObjectsDispatchThrottlingFrequency(cfg.OpenFgaServerSettings.ListObjectsDispatchThrottlingFrequency))
}
if cfg.OpenFgaServerSettings.ListObjectsDispatchThrottlingThreshold != 0 {
opts = append(opts, server.WithListObjectsDispatchThrottlingThreshold(cfg.OpenFgaServerSettings.ListObjectsDispatchThrottlingThreshold))
}
if cfg.OpenFgaServerSettings.ListObjectsDispatchThrottlingMaxThreshold != 0 {
opts = append(opts, server.WithListObjectsDispatchThrottlingMaxThreshold(cfg.OpenFgaServerSettings.ListObjectsDispatchThrottlingMaxThreshold))
}
if cfg.OpenFgaServerSettings.ListObjectsDatabaseThrottleThreshold != 0 || cfg.OpenFgaServerSettings.ListObjectsDatabaseThrottleDuration != 0 {
opts = append(opts, server.WithListObjectsDatabaseThrottle(cfg.OpenFgaServerSettings.ListObjectsDatabaseThrottleThreshold, cfg.OpenFgaServerSettings.ListObjectsDatabaseThrottleDuration))
}
// ListUsers settings
if cfg.OpenFgaServerSettings.ListUsersDeadline != 0 {
opts = append(opts, server.WithListUsersDeadline(cfg.OpenFgaServerSettings.ListUsersDeadline))
}
if cfg.OpenFgaServerSettings.ListUsersMaxResults != 0 {
opts = append(opts, server.WithListUsersMaxResults(cfg.OpenFgaServerSettings.ListUsersMaxResults))
}
if cfg.OpenFgaServerSettings.MaxConcurrentReadsForListUsers != 0 {
opts = append(opts, server.WithMaxConcurrentReadsForListUsers(cfg.OpenFgaServerSettings.MaxConcurrentReadsForListUsers))
}
if cfg.OpenFgaServerSettings.ListUsersDispatchThrottlingEnabled {
opts = append(opts, server.WithListUsersDispatchThrottlingEnabled(cfg.OpenFgaServerSettings.ListUsersDispatchThrottlingEnabled))
}
if cfg.OpenFgaServerSettings.ListUsersDispatchThrottlingFrequency != 0 {
opts = append(opts, server.WithListUsersDispatchThrottlingFrequency(cfg.OpenFgaServerSettings.ListUsersDispatchThrottlingFrequency))
}
if cfg.OpenFgaServerSettings.ListUsersDispatchThrottlingThreshold != 0 {
opts = append(opts, server.WithListUsersDispatchThrottlingThreshold(cfg.OpenFgaServerSettings.ListUsersDispatchThrottlingThreshold))
}
if cfg.OpenFgaServerSettings.ListUsersDispatchThrottlingMaxThreshold != 0 {
opts = append(opts, server.WithListUsersDispatchThrottlingMaxThreshold(cfg.OpenFgaServerSettings.ListUsersDispatchThrottlingMaxThreshold))
}
if cfg.OpenFgaServerSettings.ListUsersDatabaseThrottleThreshold != 0 || cfg.OpenFgaServerSettings.ListUsersDatabaseThrottleDuration != 0 {
opts = append(opts, server.WithListUsersDatabaseThrottle(cfg.OpenFgaServerSettings.ListUsersDatabaseThrottleThreshold, cfg.OpenFgaServerSettings.ListUsersDatabaseThrottleDuration))
}
return opts
}
func NewOpenFGAHttpServer(cfg setting.ZanzanaServerSettings, srv grpcserver.Provider) (*http.Server, error) {
dialOpts := []grpc.DialOption{
grpc.WithTransportCredentials(insecure.NewCredentials()),
+139
View File
@@ -37,6 +37,8 @@ type ZanzanaServerSettings struct {
OpenFGAHttpAddr string
// Cache settings
CacheSettings OpenFgaCacheSettings
// OpenFGA server settings
OpenFgaServerSettings OpenFgaServerSettings
// Max number of results returned by ListObjects() query. Default is 1000.
ListObjectsMaxResults uint32
// Deadline for the ListObjects() query. Default is 3 seconds.
@@ -50,6 +52,92 @@ type ZanzanaServerSettings struct {
AllowInsecure bool
}
type OpenFgaServerSettings struct {
// ListObjects settings
// Max number of concurrent datastore reads for ListObjects queries
MaxConcurrentReadsForListObjects uint32
// Enable dispatch throttling for ListObjects queries
ListObjectsDispatchThrottlingEnabled bool
// Frequency for dispatch throttling in ListObjects queries
ListObjectsDispatchThrottlingFrequency time.Duration
// Threshold for dispatch throttling in ListObjects queries
ListObjectsDispatchThrottlingThreshold uint32
// Max threshold for dispatch throttling in ListObjects queries
ListObjectsDispatchThrottlingMaxThreshold uint32
// Database throttle threshold for ListObjects queries
ListObjectsDatabaseThrottleThreshold int
// Database throttle duration for ListObjects queries
ListObjectsDatabaseThrottleDuration time.Duration
// ListUsers settings
// Deadline for ListUsers queries
ListUsersDeadline time.Duration
// Max number of results returned by ListUsers queries
ListUsersMaxResults uint32
// Max number of concurrent datastore reads for ListUsers queries
MaxConcurrentReadsForListUsers uint32
// Enable dispatch throttling for ListUsers queries
ListUsersDispatchThrottlingEnabled bool
// Frequency for dispatch throttling in ListUsers queries
ListUsersDispatchThrottlingFrequency time.Duration
// Threshold for dispatch throttling in ListUsers queries
ListUsersDispatchThrottlingThreshold uint32
// Max threshold for dispatch throttling in ListUsers queries
ListUsersDispatchThrottlingMaxThreshold uint32
// Database throttle threshold for ListUsers queries
ListUsersDatabaseThrottleThreshold int
// Database throttle duration for ListUsers queries
ListUsersDatabaseThrottleDuration time.Duration
// Check settings
// Max number of concurrent datastore reads for Check queries
MaxConcurrentReadsForCheck uint32
// Database throttle threshold for Check queries
CheckDatabaseThrottleThreshold int
// Database throttle duration for Check queries
CheckDatabaseThrottleDuration time.Duration
// Batch check settings
// Max number of concurrent checks per batch check request
MaxConcurrentChecksPerBatchCheck uint32
// Max number of checks per batch check request
MaxChecksPerBatchCheck uint32
// Resolve node settings
// Max number of nodes that can be resolved in a single query
ResolveNodeLimit uint32
// Max breadth of nodes that can be resolved in a single query
ResolveNodeBreadthLimit uint32
// Dispatch throttling settings for Check resolver
// Enable dispatch throttling for Check resolver
DispatchThrottlingCheckResolverEnabled bool
// Frequency for dispatch throttling in Check resolver
DispatchThrottlingCheckResolverFrequency time.Duration
// Threshold for dispatch throttling in Check resolver
DispatchThrottlingCheckResolverThreshold uint32
// Max threshold for dispatch throttling in Check resolver
DispatchThrottlingCheckResolverMaxThreshold uint32
// Shadow check/query settings
// Timeout for shadow check resolver
ShadowCheckResolverTimeout time.Duration
// Timeout for shadow ListObjects query
ShadowListObjectsQueryTimeout time.Duration
// Max delta items for shadow ListObjects query
ShadowListObjectsQueryMaxDeltaItems int
// Request settings
// Global request timeout
RequestTimeout time.Duration
// Max size in bytes for authorization model
MaxAuthorizationModelSizeInBytes int
// Size of the authorization model cache
AuthorizationModelCacheSize int
// Offset for changelog horizon
ChangelogHorizonOffset int
}
// Parameters to configure OpenFGA cache.
type OpenFgaCacheSettings struct {
// Number of items that will be kept in the in-memory cache used to resolve Check queries.
@@ -156,5 +244,56 @@ func (cfg *Cfg) readZanzanaSettings() {
zs.CacheSettings.SharedIteratorLimit = uint32(serverSec.Key("shared_iterator_limit").MustUint(1000))
zs.CacheSettings.SharedIteratorTTL = serverSec.Key("shared_iterator_ttl").MustDuration(10 * time.Second)
openfgaSec := cfg.SectionWithEnvOverrides("openfga")
// ListObjects settings
zs.OpenFgaServerSettings.MaxConcurrentReadsForListObjects = uint32(openfgaSec.Key("max_concurrent_reads_for_list_objects").MustUint(0))
zs.OpenFgaServerSettings.ListObjectsDispatchThrottlingEnabled = openfgaSec.Key("list_objects_dispatch_throttling_enabled").MustBool(false)
zs.OpenFgaServerSettings.ListObjectsDispatchThrottlingFrequency = openfgaSec.Key("list_objects_dispatch_throttling_frequency").MustDuration(0)
zs.OpenFgaServerSettings.ListObjectsDispatchThrottlingThreshold = uint32(openfgaSec.Key("list_objects_dispatch_throttling_threshold").MustUint(0))
zs.OpenFgaServerSettings.ListObjectsDispatchThrottlingMaxThreshold = uint32(openfgaSec.Key("list_objects_dispatch_throttling_max_threshold").MustUint(0))
zs.OpenFgaServerSettings.ListObjectsDatabaseThrottleThreshold = openfgaSec.Key("list_objects_database_throttle_threshold").MustInt(0)
zs.OpenFgaServerSettings.ListObjectsDatabaseThrottleDuration = openfgaSec.Key("list_objects_database_throttle_duration").MustDuration(0)
// ListUsers settings
zs.OpenFgaServerSettings.ListUsersDeadline = openfgaSec.Key("list_users_deadline").MustDuration(0)
zs.OpenFgaServerSettings.ListUsersMaxResults = uint32(openfgaSec.Key("list_users_max_results").MustUint(0))
zs.OpenFgaServerSettings.MaxConcurrentReadsForListUsers = uint32(openfgaSec.Key("max_concurrent_reads_for_list_users").MustUint(0))
zs.OpenFgaServerSettings.ListUsersDispatchThrottlingEnabled = openfgaSec.Key("list_users_dispatch_throttling_enabled").MustBool(false)
zs.OpenFgaServerSettings.ListUsersDispatchThrottlingFrequency = openfgaSec.Key("list_users_dispatch_throttling_frequency").MustDuration(0)
zs.OpenFgaServerSettings.ListUsersDispatchThrottlingThreshold = uint32(openfgaSec.Key("list_users_dispatch_throttling_threshold").MustUint(0))
zs.OpenFgaServerSettings.ListUsersDispatchThrottlingMaxThreshold = uint32(openfgaSec.Key("list_users_dispatch_throttling_max_threshold").MustUint(0))
zs.OpenFgaServerSettings.ListUsersDatabaseThrottleThreshold = openfgaSec.Key("list_users_database_throttle_threshold").MustInt(0)
zs.OpenFgaServerSettings.ListUsersDatabaseThrottleDuration = openfgaSec.Key("list_users_database_throttle_duration").MustDuration(0)
// Check settings
zs.OpenFgaServerSettings.MaxConcurrentReadsForCheck = uint32(openfgaSec.Key("max_concurrent_reads_for_check").MustUint(0))
zs.OpenFgaServerSettings.CheckDatabaseThrottleThreshold = openfgaSec.Key("check_database_throttle_threshold").MustInt(0)
zs.OpenFgaServerSettings.CheckDatabaseThrottleDuration = openfgaSec.Key("check_database_throttle_duration").MustDuration(0)
// Batch check settings
zs.OpenFgaServerSettings.MaxConcurrentChecksPerBatchCheck = uint32(openfgaSec.Key("max_concurrent_checks_per_batch_check").MustUint(0))
zs.OpenFgaServerSettings.MaxChecksPerBatchCheck = uint32(openfgaSec.Key("max_checks_per_batch_check").MustUint(0))
// Resolve node settings
zs.OpenFgaServerSettings.ResolveNodeLimit = uint32(openfgaSec.Key("resolve_node_limit").MustUint(0))
zs.OpenFgaServerSettings.ResolveNodeBreadthLimit = uint32(openfgaSec.Key("resolve_node_breadth_limit").MustUint(0))
// Dispatch throttling settings for Check resolver
zs.OpenFgaServerSettings.DispatchThrottlingCheckResolverEnabled = openfgaSec.Key("dispatch_throttling_check_resolver_enabled").MustBool(false)
zs.OpenFgaServerSettings.DispatchThrottlingCheckResolverFrequency = openfgaSec.Key("dispatch_throttling_check_resolver_frequency").MustDuration(0)
zs.OpenFgaServerSettings.DispatchThrottlingCheckResolverThreshold = uint32(openfgaSec.Key("dispatch_throttling_check_resolver_threshold").MustUint(0))
zs.OpenFgaServerSettings.DispatchThrottlingCheckResolverMaxThreshold = uint32(openfgaSec.Key("dispatch_throttling_check_resolver_max_threshold").MustUint(0))
// Shadow check/query settings
zs.OpenFgaServerSettings.ShadowCheckResolverTimeout = openfgaSec.Key("shadow_check_resolver_timeout").MustDuration(0)
zs.OpenFgaServerSettings.ShadowListObjectsQueryTimeout = openfgaSec.Key("shadow_list_objects_query_timeout").MustDuration(0)
zs.OpenFgaServerSettings.ShadowListObjectsQueryMaxDeltaItems = openfgaSec.Key("shadow_list_objects_query_max_delta_items").MustInt(0)
zs.OpenFgaServerSettings.RequestTimeout = openfgaSec.Key("request_timeout").MustDuration(0)
zs.OpenFgaServerSettings.MaxAuthorizationModelSizeInBytes = openfgaSec.Key("max_authorization_model_size_in_bytes").MustInt(0)
zs.OpenFgaServerSettings.AuthorizationModelCacheSize = openfgaSec.Key("authorization_model_cache_size").MustInt(0)
zs.OpenFgaServerSettings.ChangelogHorizonOffset = openfgaSec.Key("changelog_horizon_offset").MustInt(0)
cfg.ZanzanaServer = zs
}