diff --git a/pkg/eval/ievaluator.go b/pkg/eval/ievaluator.go index 7f772f461..af37e5102 100644 --- a/pkg/eval/ievaluator.go +++ b/pkg/eval/ievaluator.go @@ -12,19 +12,13 @@ const ( NotificationUpdate StateChangeNotificationType = "update" ) -type StateChangeNotification struct { - Type StateChangeNotificationType `json:"type"` - Source string `json:"source"` - FlagKey string `json:"flagKey"` -} - /* IEvaluator implementations store the state of the flags, do parsing and validation of the flag state and evaluate flags in response to handlers. */ type IEvaluator interface { GetState() (string, error) - SetState(source string, state string) ([]StateChangeNotification, error) + SetState(source string, state string) (map[string]interface{}, error) ResolveBooleanValue( reqID string, @@ -47,26 +41,3 @@ type IEvaluator interface { flagKey string, context *structpb.Struct) (value map[string]any, variant string, reasons string, err error) } - -func (s *StateChangeNotification) ToMap() map[string]interface{} { - return map[string]interface{}{ - "type": string(s.Type), - "source": s.Source, - "flagKey": s.FlagKey, - } -} - -func StateChangeNotificationsToMap(scns []StateChangeNotification) map[string]interface{} { - m := make(map[string]interface{}, len(scns)) - - for _, scn := range scns { - m[scn.FlagKey] = map[string]interface{}{ - "type": string(scn.Type), - "source": scn.Source, - } - } - - return map[string]interface{}{ - "flags": m, - } -} diff --git a/pkg/eval/json_evaluator.go b/pkg/eval/json_evaluator.go index 8aeba0ea5..e6a1277d3 100644 --- a/pkg/eval/json_evaluator.go +++ b/pkg/eval/json_evaluator.go @@ -49,7 +49,7 @@ func (je *JSONEvaluator) GetState() (string, error) { return string(data), nil } -func (je *JSONEvaluator) SetState(source string, state string) ([]StateChangeNotification, error) { +func (je *JSONEvaluator) SetState(source string, state string) (map[string]interface{}, error) { schemaLoader := gojsonschema.NewStringLoader(schema.FlagdDefinitions) flagStringLoader := gojsonschema.NewStringLoader(state) result, err := gojsonschema.Validate(schemaLoader, flagStringLoader) diff --git a/pkg/eval/json_evaluator_model.go b/pkg/eval/json_evaluator_model.go index d85559674..97076ceba 100644 --- a/pkg/eval/json_evaluator_model.go +++ b/pkg/eval/json_evaluator_model.go @@ -16,18 +16,17 @@ type Evaluators struct { Evaluators map[string]json.RawMessage `json:"$evaluators"` } -func (f Flags) Merge(logger *logger.Logger, source string, ff Flags) (Flags, []StateChangeNotification) { - notifications := []StateChangeNotification{} +func (f Flags) Merge(logger *logger.Logger, source string, ff Flags) (Flags, map[string]interface{}) { + notifications := map[string]interface{}{} result := Flags{Flags: make(map[string]Flag)} for k, v := range f.Flags { if v.Source == source { if _, ok := ff.Flags[k]; !ok { // flag has been deleted - notifications = append(notifications, StateChangeNotification{ - Type: NotificationDelete, - Source: source, - FlagKey: k, - }) + notifications[k] = map[string]interface{}{ + "type": string(NotificationDelete), + "source": source, + } continue } } @@ -37,11 +36,10 @@ func (f Flags) Merge(logger *logger.Logger, source string, ff Flags) (Flags, []S v.Source = source val, ok := result.Flags[k] if !ok { - notifications = append(notifications, StateChangeNotification{ - Type: NotificationCreate, - Source: source, - FlagKey: k, - }) + notifications[k] = map[string]interface{}{ + "type": string(NotificationCreate), + "source": source, + } } else if !reflect.DeepEqual(val, v) { if val.Source != source { logger.Warn( @@ -53,11 +51,10 @@ func (f Flags) Merge(logger *logger.Logger, source string, ff Flags) (Flags, []S ), ) } - notifications = append(notifications, StateChangeNotification{ - Type: NotificationUpdate, - Source: source, - FlagKey: k, - }) + notifications[k] = map[string]interface{}{ + "type": string(NotificationUpdate), + "source": source, + } } result.Flags[k] = v } diff --git a/pkg/eval/json_evaluator_test.go b/pkg/eval/json_evaluator_test.go index fd2132381..96a986338 100644 --- a/pkg/eval/json_evaluator_test.go +++ b/pkg/eval/json_evaluator_test.go @@ -744,35 +744,35 @@ func TestMergeFlags(t *testing.T) { new eval.Flags newSource string want eval.Flags - wantNotifs []eval.StateChangeNotification + wantNotifs map[string]interface{} }{ { name: "both nil", current: eval.Flags{Flags: nil}, new: eval.Flags{Flags: nil}, want: eval.Flags{Flags: map[string]eval.Flag{}}, - wantNotifs: []eval.StateChangeNotification{}, + wantNotifs: map[string]interface{}{}, }, { name: "both empty flags", current: eval.Flags{Flags: map[string]eval.Flag{}}, new: eval.Flags{Flags: map[string]eval.Flag{}}, want: eval.Flags{Flags: map[string]eval.Flag{}}, - wantNotifs: []eval.StateChangeNotification{}, + wantNotifs: map[string]interface{}{}, }, { name: "empty current", current: eval.Flags{Flags: nil}, new: eval.Flags{Flags: map[string]eval.Flag{}}, want: eval.Flags{Flags: map[string]eval.Flag{}}, - wantNotifs: []eval.StateChangeNotification{}, + wantNotifs: map[string]interface{}{}, }, { name: "empty new", current: eval.Flags{Flags: map[string]eval.Flag{}}, new: eval.Flags{Flags: nil}, want: eval.Flags{Flags: map[string]eval.Flag{}}, - wantNotifs: []eval.StateChangeNotification{}, + wantNotifs: map[string]interface{}{}, }, { name: "extra fields on each", @@ -798,8 +798,8 @@ func TestMergeFlags(t *testing.T) { Source: "2", }, }}, - wantNotifs: []eval.StateChangeNotification{ - {Type: "write", Source: "2", FlagKey: "paka"}, + wantNotifs: map[string]interface{}{ + "paka": map[string]interface{}{"type": "write", "source": "2"}, }, }, { @@ -815,9 +815,9 @@ func TestMergeFlags(t *testing.T) { "waka": {DefaultVariant: "on"}, "paka": {DefaultVariant: "on"}, }}, - wantNotifs: []eval.StateChangeNotification{ - {Type: "update", FlagKey: "waka"}, - {Type: "write", FlagKey: "paka"}, + wantNotifs: map[string]interface{}{ + "waka": map[string]interface{}{"type": "update", "source": ""}, + "paka": map[string]interface{}{"type": "write", "source": ""}, }, }, { @@ -831,7 +831,7 @@ func TestMergeFlags(t *testing.T) { want: eval.Flags{Flags: map[string]eval.Flag{ "hello": {DefaultVariant: "off"}, }}, - wantNotifs: []eval.StateChangeNotification{}, + wantNotifs: map[string]interface{}{}, }, } diff --git a/pkg/eval/mock/ievaluator.go b/pkg/eval/mock/ievaluator.go index 6cf92db5c..5a31d97a3 100644 --- a/pkg/eval/mock/ievaluator.go +++ b/pkg/eval/mock/ievaluator.go @@ -8,7 +8,6 @@ import ( reflect "reflect" gomock "github.com/golang/mock/gomock" - eval "github.com/open-feature/flagd/pkg/eval" structpb "google.golang.org/protobuf/types/known/structpb" ) @@ -136,10 +135,10 @@ func (mr *MockIEvaluatorMockRecorder) ResolveStringValue(reqID, flagKey, context } // SetState mocks base method. -func (m *MockIEvaluator) SetState(source, state string) ([]eval.StateChangeNotification, error) { +func (m *MockIEvaluator) SetState(source, state string) (map[string]interface{}, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SetState", source, state) - ret0, _ := ret[0].([]eval.StateChangeNotification) + ret0, _ := ret[0].(map[string]interface{}) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/pkg/runtime/runtime.go b/pkg/runtime/runtime.go index ca22d4147..81def2c68 100644 --- a/pkg/runtime/runtime.go +++ b/pkg/runtime/runtime.go @@ -83,7 +83,9 @@ func (r *Runtime) updateState(ctx context.Context, syncr sync.ISync) error { r.Service.Notify(service.Notification{ Type: service.ConfigurationChange, - Data: eval.StateChangeNotificationsToMap(notifications), + Data: map[string]interface{}{ + "flags": notifications, + }, }) return nil }