@@ -3,14 +3,15 @@ package flagd
33import (
44 "errors"
55 "fmt"
6+ "os"
7+ "strconv"
8+ "strings"
9+
610 "github.com/go-logr/logr"
711 "github.com/open-feature/flagd/core/pkg/sync"
812 "github.com/open-feature/go-sdk-contrib/providers/flagd/internal/cache"
913 "github.com/open-feature/go-sdk-contrib/providers/flagd/internal/logger"
1014 "google.golang.org/grpc"
11- "os"
12- "strconv"
13- "strings"
1415)
1516
1617type ResolverType string
@@ -26,6 +27,7 @@ const (
2627 defaultHost = "localhost"
2728 defaultResolver = rpc
2829 defaultGracePeriod = 5
30+ defaultFatalStatusCodes = ""
2931
3032 rpc ResolverType = "rpc"
3133 inProcess ResolverType = "in-process"
@@ -45,6 +47,7 @@ const (
4547 flagdOfflinePathEnvironmentVariableName = "FLAGD_OFFLINE_FLAG_SOURCE_PATH"
4648 flagdTargetUriEnvironmentVariableName = "FLAGD_TARGET_URI"
4749 flagdGracePeriodVariableName = "FLAGD_RETRY_GRACE_PERIOD"
50+ flagdFatalStatusCodesVariableName = "FLAGD_FATAL_STATUS_CODES"
4851)
4952
5053type ProviderConfiguration struct {
@@ -66,6 +69,7 @@ type ProviderConfiguration struct {
6669 CustomSyncProviderUri string
6770 GrpcDialOptionsOverride []grpc.DialOption
6871 RetryGracePeriod int
72+ FatalStatusCodes []string
6973
7074 log logr.Logger
7175}
@@ -80,6 +84,7 @@ func newDefaultConfiguration(log logr.Logger) *ProviderConfiguration {
8084 Resolver : defaultResolver ,
8185 Tls : defaultTLS ,
8286 RetryGracePeriod : defaultGracePeriod ,
87+ FatalStatusCodes : strings .Split (defaultFatalStatusCodes , "," ),
8388 }
8489
8590 p .updateFromEnvVar ()
@@ -130,6 +135,7 @@ func validateProviderConfiguration(p *ProviderConfiguration) error {
130135
131136// updateFromEnvVar is a utility to update configurations based on current environment variables
132137func (cfg * ProviderConfiguration ) updateFromEnvVar () {
138+
133139 portS := os .Getenv (flagdPortEnvironmentVariableName )
134140 if portS != "" {
135141 port , err := strconv .Atoi (portS )
@@ -159,17 +165,7 @@ func (cfg *ProviderConfiguration) updateFromEnvVar() {
159165 cfg .CertPath = certificatePath
160166 }
161167
162- if maxCacheSizeS := os .Getenv (flagdMaxCacheSizeEnvironmentVariableName ); maxCacheSizeS != "" {
163- maxCacheSizeFromEnv , err := strconv .Atoi (maxCacheSizeS )
164- if err != nil {
165- cfg .log .Error (err ,
166- fmt .Sprintf ("invalid env config for %s provided, using default value: %d" ,
167- flagdMaxCacheSizeEnvironmentVariableName , defaultMaxCacheSize ,
168- ))
169- } else {
170- cfg .MaxCacheSize = maxCacheSizeFromEnv
171- }
172- }
168+ cfg .MaxCacheSize = getIntFromEnvVarOrDefault (flagdMaxCacheSizeEnvironmentVariableName , defaultMaxCacheSize , cfg .log )
173169
174170 if cacheValue := os .Getenv (flagdCacheEnvironmentVariableName ); cacheValue != "" {
175171 switch cache .Type (cacheValue ) {
@@ -185,18 +181,8 @@ func (cfg *ProviderConfiguration) updateFromEnvVar() {
185181 }
186182 }
187183
188- if maxEventStreamRetriesS := os .Getenv (
189- flagdMaxEventStreamRetriesEnvironmentVariableName ); maxEventStreamRetriesS != "" {
190-
191- maxEventStreamRetries , err := strconv .Atoi (maxEventStreamRetriesS )
192- if err != nil {
193- cfg .log .Error (err ,
194- fmt .Sprintf ("invalid env config for %s provided, using default value: %d" ,
195- flagdMaxEventStreamRetriesEnvironmentVariableName , defaultMaxEventStreamRetries ))
196- } else {
197- cfg .EventStreamConnectionMaxAttempts = maxEventStreamRetries
198- }
199- }
184+ cfg .EventStreamConnectionMaxAttempts = getIntFromEnvVarOrDefault (
185+ flagdMaxEventStreamRetriesEnvironmentVariableName , defaultMaxEventStreamRetries , cfg .log )
200186
201187 if resolver := os .Getenv (flagdResolverEnvironmentVariableName ); resolver != "" {
202188 switch strings .ToLower (resolver ) {
@@ -230,12 +216,34 @@ func (cfg *ProviderConfiguration) updateFromEnvVar() {
230216 if gracePeriod := os .Getenv (flagdGracePeriodVariableName ); gracePeriod != "" {
231217 if seconds , err := strconv .Atoi (gracePeriod ); err == nil {
232218 cfg .RetryGracePeriod = seconds
233- } else {
234- // Handle parsing error
235- cfg .log .Error (err , fmt .Sprintf ("invalid grace period '%s'" , gracePeriod ))
219+ cfg .RetryGracePeriod = getIntFromEnvVarOrDefault (flagdGracePeriodVariableName , defaultGracePeriod , cfg .log )
236220 }
237221 }
238222
223+ if fatalStatusCodes := os .Getenv (flagdFatalStatusCodesVariableName ); fatalStatusCodes != "" {
224+ fatalStatusCodesArr := strings .Split (fatalStatusCodes , "," )
225+ for i , fatalStatusCode := range fatalStatusCodesArr {
226+ fatalStatusCodesArr [i ] = strings .TrimSpace (fatalStatusCode )
227+ }
228+ cfg .FatalStatusCodes = fatalStatusCodesArr
229+ }
230+ }
231+
232+ // Helper
233+
234+ func getIntFromEnvVarOrDefault (envVarName string , defaultValue int , log logr.Logger ) int {
235+ if valueFromEnv := os .Getenv (envVarName ); valueFromEnv != "" {
236+ intValue , err := strconv .Atoi (valueFromEnv )
237+ if err != nil {
238+ log .Error (err ,
239+ fmt .Sprintf ("invalid env config for %s provided, using default value: %d" ,
240+ envVarName , defaultValue ,
241+ ))
242+ } else {
243+ return intValue
244+ }
245+ }
246+ return defaultValue
239247}
240248
241249// ProviderOptions
@@ -415,3 +423,11 @@ func WithRetryGracePeriod(gracePeriod int) ProviderOption {
415423 p .RetryGracePeriod = gracePeriod
416424 }
417425}
426+
427+ // WithFatalStatusCodes allows to set a list of gRPC status codes, which will cause streams to give up
428+ // and put the provider in a PROVIDER_FATAL state
429+ func WithFatalStatusCodes (fatalStatusCodes []string ) ProviderOption {
430+ return func (p * ProviderConfiguration ) {
431+ p .FatalStatusCodes = fatalStatusCodes
432+ }
433+ }
0 commit comments