From d5d10e9a7a54d3e535a72248a4a3c1b128497b8c Mon Sep 17 00:00:00 2001 From: Ayush Sharma Date: Thu, 5 Oct 2023 13:14:38 +0530 Subject: [PATCH] Add a decorator for callback error handling --- event_decorators.go | 34 ++++++++++++++++++++++++++++++++++ event_decorators_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 event_decorators.go create mode 100644 event_decorators_test.go diff --git a/event_decorators.go b/event_decorators.go new file mode 100644 index 0000000..ad3a2e2 --- /dev/null +++ b/event_decorators.go @@ -0,0 +1,34 @@ +package fsm + +import "context" + +// CallbackWithErr is an FSM callback function that can return an error. The primary use case for this is for +// CallbackWithErr to be used as an argument to DecorateCallbackWithErrorHandling. +type CallbackWithErr func(ctx context.Context, event *Event) error + +// DecorateCallbackWithErrorHandling is a decorator for FSM callbacks that will catch any errors returned by the +// callback and set them on the event's Err field. This is useful for standardizing the way any error encountered +// during an FSM callback are handled. +// Example usage: +// +// fsm := NewFSM( +// "start", +// Events{ +// {Name: "run", Src: []string{"start"}, Dst: "end"}, +// }, +// Callbacks{ +// "before_event": DecorateCallbackWithErrorHandling( +// func(_ context.Context, e *Event) error { +// return errors.New("testing error handling decorator") +// }, +// ), +// }, +// ) +func DecorateCallbackWithErrorHandling(callback CallbackWithErr) Callback { + return func(ctx context.Context, event *Event) { + err := callback(ctx, event) + if err != nil { + event.Err = err + } + } +} diff --git a/event_decorators_test.go b/event_decorators_test.go new file mode 100644 index 0000000..b985a51 --- /dev/null +++ b/event_decorators_test.go @@ -0,0 +1,33 @@ +package fsm + +import ( + "context" + "errors" + "testing" +) + +func TestDecorateCallbackWithErrorHandling(t *testing.T) { + t.Parallel() + + fsm := NewFSM( + "start", + Events{ + {Name: "run", Src: []string{"start"}, Dst: "end"}, + }, + Callbacks{ + "before_event": DecorateCallbackWithErrorHandling( + func(_ context.Context, e *Event) error { + return errors.New("testing error handling decorator") + }, + ), + }, + ) + + err := fsm.Event(context.Background(), "run") + if err == nil { + t.Error("expected error to be returned from event") + } + if err.Error() != "testing error handling decorator" { + t.Errorf("expected error to be 'testing error handling decorator', got '%s'", err.Error()) + } +}