Skip to content

Commit

Permalink
Add router for CLI interface to work with handlers and avoid switch-c…
Browse files Browse the repository at this point in the history
…ase factories (#42)

Signed-off-by: Igor Shishkin <me@teran.dev>
  • Loading branch information
teran authored Jul 13, 2024
1 parent 9e3e8c8 commit 908a11f
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 0 deletions.
51 changes: 51 additions & 0 deletions cli/router/router.go
Original file line number Diff line number Diff line change
@@ -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
}
38 changes: 38 additions & 0 deletions cli/router/router_test.go
Original file line number Diff line number Diff line change
@@ -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)
}

0 comments on commit 908a11f

Please sign in to comment.