Skip to content

Commit

Permalink
Add fallback pattern flag to router plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
Qiyao Qin committed Dec 21, 2017
1 parent 2f4bf60 commit 6eff4d5
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 42 deletions.
9 changes: 6 additions & 3 deletions connectors/routing/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,17 @@ type Config struct {
}

// FindRouter finds the router information based on scope and namePrefix.
func (c *Config) FindRouter(scope, namePrefix string) *Rule {
func (c *Config) FindRouter(scope, namePrefix string, shouldFail bool) (*Rule, error) {
if shouldFail {
return nil, errors.New("requests failed because they are explicitly set to fail")
}
for _, router := range c.Routers {
if router.RouteTo(scope, namePrefix) {
return router
return router, nil
}
}

return c.findDefaultRouter()
return c.findDefaultRouter(), nil
}

// findDefaultRouter finds the default router information.
Expand Down
11 changes: 7 additions & 4 deletions connectors/routing/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,18 @@ routers:
cfg := testCfg.findDefaultRouter()
assert.Equal(t, cfg.Scope, "default")

cfg = testCfg.FindRouter("production", "serviceA")
cfg, _ = testCfg.FindRouter("production", "serviceA", false)
assert.Equal(t, cfg, buildRouter("production", "serviceA", "cassandra"))

cfg = testCfg.FindRouter("ebook", "apple.k")
cfg, _ = testCfg.FindRouter("ebook", "apple.k", false)
assert.Equal(t, cfg, buildRouter("ebook", "apple.*", "ebook"))

cfg = testCfg.FindRouter("ebook", "d.k")
cfg, _ = testCfg.FindRouter("ebook", "d.k", false)
assert.Equal(t, cfg, buildRouter("ebook", "*", "ebook"))

cfg = testCfg.FindRouter("a", "d.k")
cfg, _ = testCfg.FindRouter("a", "d.k", false)
assert.Equal(t, cfg, buildRouter("default", "default", "dosa"))

cfg, err = testCfg.FindRouter("ebook", "d.k", true)
assert.Contains(t, err.Error(), "requests failed because they are explicitly set to fail")
}
18 changes: 11 additions & 7 deletions connectors/routing/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ import (
)

// PluginFunc is a plugin function that takes scope, namePrefix and operation name,
// then gives wanted scope and namePrefix
type PluginFunc func(scope, namePrefix, opName string) (string, string, error)
// then gives wanted scope and namePrefix, and whether to fall into default connector
type PluginFunc func(scope, namePrefix, opName string) (string, string, bool, error)

// Connector holds a slice of configured connectors to route to
type Connector struct {
Expand Down Expand Up @@ -59,21 +59,25 @@ func NewConnector(cfg Config, connectorMap map[string]dosa.Connector, plugin Plu

// get connector by scope, namePrefix and operation name provided
func (rc *Connector) getConnector(scope string, namePrefix string, opName string) (_ dosa.Connector, err error) {
var shouldFail bool
if rc.PluginFunc != nil {
// plugin operation
// plugin should always be first considered if it exists
scope, namePrefix, err = rc.PluginFunc(scope, namePrefix, opName)
scope, namePrefix, shouldFail, err = rc.PluginFunc(scope, namePrefix, opName)
if err != nil {
return nil, errors.Wrap(err, "failed to execute getConnector due to Plugin function error")
}
}
return rc._getConnector(scope, namePrefix)
return rc._getConnector(scope, namePrefix, shouldFail)
}

// if no specific scope is found,
// Connector routes to the default scope that defined in routing config yaml file
func (rc *Connector) _getConnector(scope, namePrefix string) (dosa.Connector, error) {
router := rc.config.FindRouter(scope, namePrefix)
func (rc *Connector) _getConnector(scope, namePrefix string, shouldFail bool) (dosa.Connector, error) {
router, err := rc.config.FindRouter(scope, namePrefix, shouldFail)
if err != nil {
return nil, errors.Wrap(err, "get connector failure")
}

c, ok := rc.connectors[router.Connector]
if !ok {
Expand Down Expand Up @@ -260,4 +264,4 @@ func (rc *Connector) Shutdown() error {
return rConnErr
}
return nil
}
}
55 changes: 27 additions & 28 deletions connectors/routing/connector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,18 +202,17 @@ func TestGetConnector(t *testing.T) {
assert.NotNil(t, conn)
assert.Equal(t, reflect.TypeOf(conn), reflect.TypeOf(memory.NewConnector()))

// with plugin
rc.PluginFunc = func(scope, namePrefix, opName string) (string, string, error) {
return "ebook", "ebook-store", nil
// plugin indicates to throw out error rather than fall into default connector
rc.PluginFunc = func(scope, namePrefix, opName string) (string, string, bool, error) {
return "", "", true, nil
}

conn, err = rc.getConnector(ei.Ref.Scope, ei.Ref.NamePrefix, "Read")
assert.NoError(t, err)
assert.NotNil(t, conn)
assert.Contains(t, err.Error(), "requests failed because they are explicitly set to fail")
assert.Nil(t, conn)

// plugin returns error
rc.PluginFunc = func(scope, namePrefix, opName string) (string, string, error) {
return "", "", errors.New("")
rc.PluginFunc = func(scope, namePrefix, opName string) (string, string, bool, error) {
return "", "", true, errors.New("")
}
conn, err = rc.getConnector(ei.Ref.Scope, ei.Ref.NamePrefix, "Read")
assert.Contains(t, err.Error(), "failed to execute getConnector due to Plugin function error")
Expand Down Expand Up @@ -241,8 +240,8 @@ func TestConnector_CreateIfNotExistsDefaultScope(t *testing.T) {
"p1": dosa.FieldValue("data")})
assert.NoError(t, err)

plugin := func(scope, namePrefix, opName string) (string, string, error) {
return "", "", errors.New("dummy errors")
plugin := func(scope, namePrefix, opName string) (string, string, bool, error) {
return "", "", true, errors.New("dummy errors")
}
rc.PluginFunc = plugin
// not exist scope, use default
Expand Down Expand Up @@ -380,8 +379,8 @@ func TestConnector_Read(t *testing.T) {
"c7": dosa.FieldValue(id)}, dosa.All())
assert.True(t, dosa.ErrorIsNotFound(err))

plugin := func(scope, namePrefix, opName string) (string, string, error) {
return "", "", errors.New("dummy errors")
plugin := func(scope, namePrefix, opName string) (string, string, bool, error) {
return "", "", true, errors.New("dummy errors")
}
rc.PluginFunc = plugin
// not exist scope, use default
Expand Down Expand Up @@ -413,8 +412,8 @@ func TestMultiRead(t *testing.T) {
_, err := rc.MultiRead(ctx, testInfoRandom, testMultiValues, dosa.All())
assert.NoError(t, err)

plugin := func(scope, namePrefix, opName string) (string, string, error) {
return "", "", errors.New("dummy errors")
plugin := func(scope, namePrefix, opName string) (string, string, bool, error) {
return "", "", true, errors.New("dummy errors")
}
rc.PluginFunc = plugin
// not exist scope, use default
Expand Down Expand Up @@ -480,8 +479,8 @@ func TestConnector_Upsert(t *testing.T) {
assert.Len(t, data, 20)
assert.NotNil(t, data[0]["c6"])

plugin := func(scope, namePrefix, opName string) (string, string, error) {
return "", "", errors.New("dummy errors")
plugin := func(scope, namePrefix, opName string) (string, string, bool, error) {
return "", "", true, errors.New("dummy errors")
}
rc.PluginFunc = plugin
// not exist scope, use default
Expand All @@ -506,8 +505,8 @@ func TestConnector_MultiUpsert(t *testing.T) {
_, err := rc.MultiUpsert(ctx, testInfoRandom, testMultiValues)
assert.NoError(t, err)

plugin := func(scope, namePrefix, opName string) (string, string, error) {
return "", "", errors.New("dummy errors")
plugin := func(scope, namePrefix, opName string) (string, string, bool, error) {
return "", "", true, errors.New("dummy errors")
}
rc.PluginFunc = plugin
// not exist scope, use default
Expand Down Expand Up @@ -567,8 +566,8 @@ func TestConnector_Remove(t *testing.T) {
"c7": dosa.FieldValue(id)})
assert.NoError(t, err)

plugin := func(scope, namePrefix, opName string) (string, string, error) {
return "", "", errors.New("dummy errors")
plugin := func(scope, namePrefix, opName string) (string, string, bool, error) {
return "", "", true, errors.New("dummy errors")
}
rc.PluginFunc = plugin
// not exist scope, use default
Expand Down Expand Up @@ -656,8 +655,8 @@ func TestConnector_RemoveRange(t *testing.T) {
assert.NoError(t, err)
assert.Empty(t, data)

plugin := func(scope, namePrefix, opName string) (string, string, error) {
return "", "", errors.New("dummy errors")
plugin := func(scope, namePrefix, opName string) (string, string, bool, error) {
return "", "", true, errors.New("dummy errors")
}
rc.PluginFunc = plugin
// not exist scope, use default
Expand Down Expand Up @@ -686,8 +685,8 @@ func TestConnector_MultiRemove(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, errs)

plugin := func(scope, namePrefix, opName string) (string, string, error) {
return "", "", errors.New("dummy errors")
plugin := func(scope, namePrefix, opName string) (string, string, bool, error) {
return "", "", true, errors.New("dummy errors")
}
rc.PluginFunc = plugin
// not exist scope, use default
Expand Down Expand Up @@ -818,8 +817,8 @@ func TestConnector_Range(t *testing.T) {
assert.Empty(t, data)
assert.Empty(t, token)

plugin := func(scope, namePrefix, opName string) (string, string, error) {
return "", "", errors.New("dummy errors")
plugin := func(scope, namePrefix, opName string) (string, string, bool, error) {
return "", "", true, errors.New("dummy errors")
}
rc.PluginFunc = plugin
// not exist scope, use default
Expand Down Expand Up @@ -869,8 +868,8 @@ func TestConnector_Scan(t *testing.T) {
assert.Empty(t, data)
assert.Empty(t, token)

plugin := func(scope, namePrefix, opName string) (string, string, error) {
return "", "", errors.New("dummy errors")
plugin := func(scope, namePrefix, opName string) (string, string, bool, error) {
return "", "", true, errors.New("dummy errors")
}
rc.PluginFunc = plugin
// not exist scope, use default
Expand Down

0 comments on commit 6eff4d5

Please sign in to comment.