diff --git a/cli/router/router.go b/cli/router/router.go new file mode 100644 index 0000000..76ca596 --- /dev/null +++ b/cli/router/router.go @@ -0,0 +1,51 @@ +package router + +import ( + "context" + "sync" + + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" +) + +var ErrNoSuchRoute = errors.New("no such route") + +type Router interface { + Register(command string, fn func(ctx context.Context) error) + Call(command string) error +} + +type router struct { + ctx context.Context + mutex *sync.RWMutex + routes map[string]func(ctx context.Context) error +} + +func New(ctx context.Context) Router { + return &router{ + ctx: ctx, + mutex: &sync.RWMutex{}, + routes: make(map[string]func(ctx context.Context) error), + } +} + +func (r *router) Register(command string, fn func(ctx context.Context) error) { + r.mutex.Lock() + defer r.mutex.Unlock() + + log.Debugf("route `%s` registered", command) + + r.routes[command] = fn +} + +func (r *router) Call(command string) error { + r.mutex.RLock() + defer r.mutex.RUnlock() + + log.Tracef("route request: `%s`", command) + + if fn, ok := r.routes[command]; ok { + return fn(r.ctx) + } + return ErrNoSuchRoute +} diff --git a/cli/router/router_test.go b/cli/router/router_test.go new file mode 100644 index 0000000..fae158b --- /dev/null +++ b/cli/router/router_test.go @@ -0,0 +1,38 @@ +package router + +import ( + "context" + "testing" + + "github.com/pkg/errors" + "github.com/stretchr/testify/require" +) + +func TestRouter(t *testing.T) { + r := require.New(t) + + var ( + test1Called = 0 + test2Called = 0 + errTest1 = errors.New("blah") + ) + + rt := New(context.Background()) + rt.Register("test1", func(ctx context.Context) error { + test1Called++ + return errTest1 + }) + rt.Register("test2", func(ctx context.Context) error { + test2Called++ + return nil + }) + + err := rt.Call("test1") + r.Error(err) + r.Equal(errTest1, err) + r.Equal(1, test1Called) + + err = rt.Call("test2") + r.NoError(err) + r.Equal(1, test2Called) +}