Unleash/unleash-client-go

Features read from file cannot be cast to Feature

pschmidt88 opened this issue · 2 comments

Hello,

I think I found a bug in the current feature storage and repository implementation:
When features are read from the backup/cache file and were not (yet) fetched from the server, every feature evaluates to false/disabled.

This is because, when features are read from file, they are decoded to a generic map[string]interface{} structure,
because the type of the data holding variable is a map[string]interface{} and the decoder doesn't know to which type it should
decode the json to.

type defaultStorage struct {
appName string
path string
data map[string]interface{}
}

func (ds *defaultStorage) Load() error {
if file, err := os.Open(ds.path); err != nil {
return err
} else {
dec := json.NewDecoder(file)
if err := dec.Decode(&ds.data); err != nil {
return err
}
}
return nil
}

The repository then tries to cast this generic structure to a Feature struct (L146), which does not work, eventually returning a nil value although a valid feature exists.

func (r *repository) getToggle(key string) *api.Feature {
r.RLock()
defer r.RUnlock()
if toggle, found := r.options.storage.Get(key); found {
if feature, ok := toggle.(api.Feature); ok {
return &feature
}
}
return nil
}

To reproduce this behavior, you can:

  1. Create a client with a custom backup path
  2. Let the client persist features fetched from the server into the schema json file
  3. Stop the server
  4. Restart the client and let it read the features from the file
  5. Query an enabled toggle

The feature toggle will evaluate to false

Is there a reason why data in defaultStorage is of type map[string]interface{} and not map[string]api.Feature ?

This was fixed in #83