@@ -26,6 +26,7 @@ import (
2626 "strings"
2727 "sync"
2828 "sync/atomic"
29+ "time"
2930
3031 "github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration/internal/jsonc"
3132 "github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration/internal/refresh"
@@ -140,7 +141,7 @@ func Load(ctx context.Context, authentication AuthenticationOptions, options *Op
140141 }
141142 }
142143
143- if err := azappcfg .load (ctx ); err != nil {
144+ if err := azappcfg .startupWithRetry (ctx , options . StartupOptions . Timeout , azappcfg . load ); err != nil {
144145 return nil , err
145146 }
146147 // Set the initial load finished flag
@@ -480,6 +481,11 @@ func (azappcfg *AzureAppConfiguration) loadFeatureFlags(ctx context.Context, set
480481
481482 dedupFeatureFlags := make (map [string ]any , len (settingsResponse .settings ))
482483 for _ , setting := range settingsResponse .settings {
484+ // Skip non-feature flag settings
485+ if setting .ContentType == nil || * setting .ContentType != featureFlagContentType {
486+ continue
487+ }
488+
483489 if setting .Key != nil {
484490 var v map [string ]any
485491 if err := json .Unmarshal ([]byte (* setting .Value ), & v ); err != nil {
@@ -676,6 +682,59 @@ func (azappcfg *AzureAppConfiguration) executeFailoverPolicy(ctx context.Context
676682 return fmt .Errorf ("failed to get settings from all clients: %v" , errors )
677683}
678684
685+ // startupWithRetry implements retry logic for startup loading with timeout and exponential backoff
686+ func (azappcfg * AzureAppConfiguration ) startupWithRetry (ctx context.Context , timeout time.Duration , operation func (context.Context ) error ) error {
687+ // If no timeout is specified, use the default startup timeout
688+ if timeout <= 0 {
689+ timeout = defaultStartupTimeout
690+ }
691+
692+ // Create a context with timeout for the entire startup process
693+ startupCtx , cancel := context .WithTimeout (ctx , timeout )
694+ defer cancel ()
695+
696+ attempt := 0
697+ startTime := time .Now ()
698+
699+ for {
700+ attempt ++
701+
702+ // Try to load with the current context
703+ err := operation (startupCtx )
704+ if err == nil {
705+ return nil
706+ }
707+
708+ // Check if the error is retriable
709+ if ! (isFailoverable (err ) ||
710+ strings .Contains (err .Error (), "no client is available" ) ||
711+ strings .Contains (err .Error (), "failed to get settings from all clients" )) {
712+ return fmt .Errorf ("load from Azure App Configuration failed with non-retriable error: %w" , err )
713+ }
714+
715+ // Calculate backoff duration
716+ timeElapsed := time .Since (startTime )
717+ backoffDuration := getFixedBackoffDuration (timeElapsed )
718+ if backoffDuration == 0 {
719+ backoffDuration = calculateBackoffDuration (attempt )
720+ }
721+
722+ // Check if we have enough time left to wait and retry
723+ timeRemaining := timeout - timeElapsed
724+ if timeRemaining <= backoffDuration {
725+ return fmt .Errorf ("load from Azure App Configuration failed after %d attempts within timeout %v: %w" , attempt , timeout , err )
726+ }
727+
728+ // Wait for the backoff duration before retrying
729+ select {
730+ case <- startupCtx .Done ():
731+ return fmt .Errorf ("load from Azure App Configuration timed out: %w" , startupCtx .Err ())
732+ case <- time .After (backoffDuration ):
733+ // Continue to next retry attempt
734+ }
735+ }
736+ }
737+
679738func (azappcfg * AzureAppConfiguration ) trimPrefix (key string ) string {
680739 result := key
681740 for _ , prefix := range azappcfg .trimPrefixes {
@@ -725,7 +784,9 @@ func deduplicateSelectors(selectors []Selector) []Selector {
725784
726785func getFeatureFlagSelectors (selectors []Selector ) []Selector {
727786 for i := range selectors {
728- selectors [i ].KeyFilter = featureFlagKeyPrefix + selectors [i ].KeyFilter
787+ if selectors [i ].SnapshotName == "" {
788+ selectors [i ].KeyFilter = featureFlagKeyPrefix + selectors [i ].KeyFilter
789+ }
729790 }
730791
731792 return selectors
@@ -760,6 +821,7 @@ func configureTracingOptions(options *Options) tracing.Options {
760821 }
761822
762823 tracingOption .Host = tracing .GetHostType ()
824+ tracingOption .FMVersion = tracing .GetFeatureManagementVersion ()
763825
764826 if ! (options .KeyVaultOptions .SecretResolver == nil && options .KeyVaultOptions .Credential == nil ) {
765827 tracingOption .KeyVaultConfigured = true
0 commit comments