Skip to content

Commit 63de64a

Browse files
authored
feat: add evaluation details to finally hook (#328)
Signed-off-by: bbland1 <[email protected]>
1 parent 3c70dc2 commit 63de64a

File tree

6 files changed

+36
-36
lines changed

6 files changed

+36
-36
lines changed

openfeature/client.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ func (c *Client) evaluate(
710710
}
711711

712712
defer func() {
713-
c.finallyHooks(ctx, hookCtx, providerInvocationClientApiHooks, options)
713+
c.finallyHooks(ctx, hookCtx, providerInvocationClientApiHooks, evalDetails, options)
714714
}()
715715

716716
// bypass short-circuit logic for the Noop provider; it is essentially stateless and a "special case"
@@ -828,9 +828,9 @@ func (c *Client) errorHooks(ctx context.Context, hookCtx HookContext, hooks []Ho
828828
}
829829
}
830830

831-
func (c *Client) finallyHooks(ctx context.Context, hookCtx HookContext, hooks []Hook, options EvaluationOptions) {
831+
func (c *Client) finallyHooks(ctx context.Context, hookCtx HookContext, hooks []Hook, evalDetails InterfaceEvaluationDetails, options EvaluationOptions) {
832832
for _, hook := range hooks {
833-
hook.Finally(ctx, hookCtx, options.hookHints)
833+
hook.Finally(ctx, hookCtx,evalDetails, options.hookHints)
834834
}
835835
}
836836

openfeature/client_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1314,7 +1314,7 @@ func TestRequirement_1_7_6(t *testing.T) {
13141314
ctrl := gomock.NewController(t)
13151315
mockHook := NewMockHook(ctrl)
13161316
mockHook.EXPECT().Error(gomock.Any(), gomock.Any(), ProviderNotReadyError, gomock.Any())
1317-
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
1317+
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
13181318

13191319
notReadyEventingProvider := struct {
13201320
FeatureProvider
@@ -1377,7 +1377,7 @@ func TestRequirement_1_7_7(t *testing.T) {
13771377
ctrl := gomock.NewController(t)
13781378
mockHook := NewMockHook(ctrl)
13791379
mockHook.EXPECT().Error(gomock.Any(), gomock.Any(), ProviderFatalError, gomock.Any())
1380-
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
1380+
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
13811381

13821382
client := GetApiInstance().GetNamedClient(t.Name())
13831383
client.AddHooks(mockHook)

openfeature/hooks.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ type Hook interface {
99
Before(ctx context.Context, hookContext HookContext, hookHints HookHints) (*EvaluationContext, error)
1010
After(ctx context.Context, hookContext HookContext, flagEvaluationDetails InterfaceEvaluationDetails, hookHints HookHints) error
1111
Error(ctx context.Context, hookContext HookContext, err error, hookHints HookHints)
12-
Finally(ctx context.Context, hookContext HookContext, hookHints HookHints)
12+
Finally(ctx context.Context, hookContext HookContext, flagEvaluationDetails InterfaceEvaluationDetails, hookHints HookHints)
1313
}
1414

1515
// HookHints contains a map of hints for hooks
@@ -108,4 +108,4 @@ func (UnimplementedHook) After(context.Context, HookContext, InterfaceEvaluation
108108
return nil
109109
}
110110
func (UnimplementedHook) Error(context.Context, HookContext, error, HookHints) {}
111-
func (UnimplementedHook) Finally(context.Context, HookContext, HookHints) {}
111+
func (UnimplementedHook) Finally(context.Context, HookContext, InterfaceEvaluationDetails, HookHints) {}

openfeature/hooks/logging_hook.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,6 @@ func (h *LoggingHook) Error(ctx context.Context, hookContext of.HookContext, err
9191
h.logger.Error("Error stage", args...)
9292
}
9393

94-
func (h *LoggingHook) Finally(ctx context.Context, hCtx of.HookContext, hint of.HookHints) {
94+
func (h *LoggingHook) Finally(ctx context.Context, hCtx of.HookContext, flagEvaluationDetails of.InterfaceEvaluationDetails, hint of.HookHints) {
9595

9696
}

openfeature/hooks_mock_test.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

openfeature/hooks_test.go

+26-26
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ func TestRequirement_4_3_2(t *testing.T) {
174174
mockProvider.EXPECT().StringEvaluation(gomock.Any(), flagKey, defaultValue, flatCtx).
175175
After(mockHook.EXPECT().Before(gomock.Any(), gomock.Any(), gomock.Any()))
176176
mockHook.EXPECT().After(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
177-
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
177+
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
178178

179179
_, err = GetApiInstance().GetNamedClient(t.Name()).StringValueDetails(context.Background(), flagKey, defaultValue, evalCtx, WithHooks(mockHook))
180180
if err != nil {
@@ -244,9 +244,9 @@ func TestRequirement_4_3_3(t *testing.T) {
244244
mockHook2.EXPECT().Before(gomock.Any(), hook2Ctx, gomock.Any())
245245

246246
mockHook1.EXPECT().After(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
247-
mockHook1.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
247+
mockHook1.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
248248
mockHook2.EXPECT().After(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
249-
mockHook2.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
249+
mockHook2.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
250250

251251
_, err = client.StringValueDetails(context.Background(), flagKey, defaultValue, evalCtx, WithHooks(mockHook1, mockHook2))
252252
if err != nil {
@@ -321,7 +321,7 @@ func TestRequirement_4_3_4(t *testing.T) {
321321
}
322322
mockProvider.EXPECT().StringEvaluation(gomock.Any(), flagKey, defaultValue, flattenContext(expectedMergedContext))
323323
mockHook.EXPECT().After(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
324-
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
324+
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
325325

326326
_, err = client.StringValueDetails(context.Background(), flagKey, defaultValue, invEvalCtx, WithHooks(mockHook))
327327
if err != nil {
@@ -357,7 +357,7 @@ func TestRequirement_4_3_5(t *testing.T) {
357357
// assert that the After hooks are executed after the flag evaluation
358358
mockHook.EXPECT().After(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
359359
After(mockProvider.EXPECT().StringEvaluation(gomock.Any(), flagKey, defaultValue, flatCtx))
360-
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
360+
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
361361

362362
_, err = GetApiInstance().GetNamedClient(t.Name()).StringValueDetails(context.Background(), flagKey, defaultValue, evalCtx, WithHooks(mockHook))
363363
if err != nil {
@@ -407,7 +407,7 @@ func TestRequirement_4_3_6(t *testing.T) {
407407
// assert that the Error hooks are executed after the failed Before hooks
408408
mockHook.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
409409
After(mockHook.EXPECT().Before(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("forced")))
410-
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
410+
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
411411

412412
_, err = GetApiInstance().GetNamedClient(t.Name()).StringValueDetails(context.Background(), flagKey, defaultValue, evalCtx, WithHooks(mockHook))
413413
if err == nil {
@@ -440,7 +440,7 @@ func TestRequirement_4_3_6(t *testing.T) {
440440
},
441441
}),
442442
)
443-
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
443+
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
444444

445445
_, err = GetApiInstance().GetNamedClient(t.Name()).StringValueDetails(context.Background(), flagKey, defaultValue, evalCtx, WithHooks(mockHook))
446446
if err == nil {
@@ -467,7 +467,7 @@ func TestRequirement_4_3_6(t *testing.T) {
467467
// assert that the Error hooks are executed after the failed After hooks
468468
mockHook.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
469469
After(mockHook.EXPECT().After(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("forced")))
470-
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
470+
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
471471

472472
_, err = GetApiInstance().GetNamedClient(t.Name()).StringValueDetails(context.Background(), flagKey, defaultValue, evalCtx, WithHooks(mockHook))
473473
if err == nil {
@@ -514,7 +514,7 @@ func TestRequirement_4_3_7(t *testing.T) {
514514
mockProvider.EXPECT().Hooks().AnyTimes()
515515

516516
// assert that the Finally hook runs after the Before & After stages
517-
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any()).
517+
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
518518
After(mockHook.EXPECT().After(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())).
519519
After(mockHook.EXPECT().Before(gomock.Any(), gomock.Any(), gomock.Any()))
520520
mockProvider.EXPECT().StringEvaluation(context.Background(), flagKey, defaultValue, flatCtx)
@@ -541,7 +541,7 @@ func TestRequirement_4_3_7(t *testing.T) {
541541

542542
mockHook.EXPECT().Before(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("forced"))
543543
// assert that the Finally hook runs after the Error stage
544-
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any()).
544+
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
545545
After(mockHook.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()))
546546

547547
_, err = GetApiInstance().GetNamedClient(t.Name()).StringValueDetails(context.Background(), flagKey, defaultValue, evalCtx, WithHooks(mockHook))
@@ -554,7 +554,7 @@ func TestRequirement_4_3_7(t *testing.T) {
554554
mockHook := NewMockHook(ctrl)
555555

556556
type requirement interface {
557-
Finally(ctx context.Context, hookContext HookContext, hookHints HookHints)
557+
Finally(ctx context.Context, hookContext HookContext, flagEvaluationDetails InterfaceEvaluationDetails, hookHints HookHints)
558558
}
559559

560560
var hookI interface{} = mockHook
@@ -673,10 +673,10 @@ func TestRequirement_4_4_2(t *testing.T) {
673673
After(mockProviderHook.EXPECT().After(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()))
674674

675675
// finally: Invocation, Client, API
676-
mockAPIHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any()).
677-
After(mockClientHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())).
678-
After(mockInvocationHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())).
679-
After(mockProviderHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any()))
676+
mockAPIHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
677+
After(mockClientHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())).
678+
After(mockInvocationHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())).
679+
After(mockProviderHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()))
680680

681681
mockProvider.EXPECT().StringEvaluation(context.Background(), flagKey, defaultValue, flatCtx)
682682

@@ -717,10 +717,10 @@ func TestRequirement_4_4_2(t *testing.T) {
717717
After(mockInvocationHook.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())).
718718
After(mockProviderHook.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()))
719719

720-
mockProviderHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
721-
mockInvocationHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
722-
mockClientHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
723-
mockAPIHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
720+
mockProviderHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
721+
mockInvocationHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
722+
mockClientHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
723+
mockAPIHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
724724

725725
_, err = client.StringValueDetails(context.Background(), flagKey, defaultValue, evalCtx, WithHooks(mockInvocationHook))
726726
if err == nil {
@@ -779,9 +779,9 @@ func TestRequirement_4_4_6(t *testing.T) {
779779
mockHook1.EXPECT().Before(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("forced"))
780780
// the lack of mockHook2.EXPECT().Before() asserts that remaining hooks aren't invoked after an error
781781
mockHook1.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
782-
mockHook1.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
782+
mockHook1.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
783783
mockHook2.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
784-
mockHook2.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
784+
mockHook2.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
785785

786786
_, err = client.StringValueDetails(context.Background(), flagKey, defaultValue, evalCtx, WithHooks(mockHook1, mockHook2))
787787
if err == nil {
@@ -814,9 +814,9 @@ func TestRequirement_4_4_6(t *testing.T) {
814814
mockHook1.EXPECT().After(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("forced"))
815815
// the lack of mockHook2.EXPECT().After() asserts that remaining hooks aren't invoked after an error
816816
mockHook1.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
817-
mockHook1.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
817+
mockHook1.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
818818
mockHook2.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
819-
mockHook2.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
819+
mockHook2.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
820820

821821
mockProvider.EXPECT().StringEvaluation(context.Background(), flagKey, defaultValue, flatCtx)
822822

@@ -850,7 +850,7 @@ func TestRequirement_4_4_7(t *testing.T) {
850850

851851
mockHook.EXPECT().Before(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("forced"))
852852
mockHook.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
853-
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
853+
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
854854

855855
res, err := GetApiInstance().GetNamedClient(t.Name()).StringValueDetails(context.Background(), flagKey, defaultValue, evalCtx, WithHooks(mockHook))
856856
if err == nil {
@@ -900,7 +900,7 @@ func TestRequirement_4_5_2(t *testing.T) {
900900

901901
mockHook.EXPECT().Before(gomock.Any(), gomock.Any(), hookHints)
902902
mockHook.EXPECT().After(gomock.Any(), gomock.Any(), gomock.Any(), hookHints)
903-
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), hookHints)
903+
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), hookHints)
904904

905905
mockProvider.EXPECT().StringEvaluation(context.Background(), flagKey, defaultValue, flatCtx)
906906

@@ -933,7 +933,7 @@ func TestRequirement_4_5_2(t *testing.T) {
933933

934934
mockHook.EXPECT().Before(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("forced"))
935935
mockHook.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any(), hookHints)
936-
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any())
936+
mockHook.EXPECT().Finally(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
937937

938938
_, err = client.StringValueDetails(context.Background(), flagKey, defaultValue, evalCtx, WithHooks(mockHook), WithHookHints(hookHints))
939939
if err == nil {

0 commit comments

Comments
 (0)