Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fallback pattern flag to router plugin #257

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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