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

feat : add script routing functionality #2669

Merged
merged 21 commits into from
May 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
add more test case, remove unuse field,struct,interface
Signed-off-by: YarBor <yarbor.ww@gmail.com>
  • Loading branch information
YarBor committed May 12, 2024
commit 7ea53671854619469507c61e762cac458a7e0e20
22 changes: 9 additions & 13 deletions cluster/router/script/instance/instances_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,50 +62,46 @@ func setInstances(tpName string, instance ScriptInstances) {
// if script change input Invoker's url during Route() call ,
// it will influence call Route() next time ,
// there are no operation to recover .
type scriptInvokerPack interface {
protocol.Invoker
}

type scriptInvokerPackImpl struct {
type scriptInvokerPack struct {
isRan bool
copiedURL *common.URL
invoker protocol.Invoker
isRan bool
}

func (f *scriptInvokerPackImpl) GetURL() *common.URL {
func (f *scriptInvokerPack) GetURL() *common.URL {
return f.copiedURL
}

func (f *scriptInvokerPackImpl) IsAvailable() bool {
func (f *scriptInvokerPack) IsAvailable() bool {
if !f.isRan {
return true
} else {
return f.invoker.IsAvailable()
}
}

func (f *scriptInvokerPackImpl) Destroy() {
func (f *scriptInvokerPack) Destroy() {
if !f.isRan {
panic("Destroy should not be called")
} else {
f.invoker.Destroy()
}
}

func (f *scriptInvokerPackImpl) Invoke(ctx context.Context, inv protocol.Invocation) protocol.Result {
func (f *scriptInvokerPack) Invoke(ctx context.Context, inv protocol.Invocation) protocol.Result {
if !f.isRan {
panic("Invoke should not be called")
} else {
return f.invoker.Invoke(ctx, inv)
}
}

func (f *scriptInvokerPackImpl) setRanMode() {
func (f *scriptInvokerPack) setRanMode() {
f.isRan = true
}

func newScriptInvokerImpl(invoker protocol.Invoker) *scriptInvokerPackImpl {
return &scriptInvokerPackImpl{
func newScriptInvokerImpl(invoker protocol.Invoker) *scriptInvokerPack {
return &scriptInvokerPack{
copiedURL: invoker.GetURL().Clone(),
invoker: invoker,
isRan: false,
Expand Down
4 changes: 2 additions & 2 deletions cluster/router/script/instance/js_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@ func (i *jsInstances) Run(_ string, invokers []protocol.Invoker, invocation prot

result := make([]protocol.Invoker, 0, len(rtInvokersArr))
for _, res := range rtInvokersArr {
if i, ok := res.(*scriptInvokerPackImpl); ok {
if i, ok := res.(*scriptInvokerPack); ok {
i.setRanMode()
result = append(result, res.(protocol.Invoker))
} else {
return invokers, fmt.Errorf("invalid element type , it should be (*scriptInvokerPackImpl) , but type is : %s)", reflect.TypeOf(res).String())
return invokers, fmt.Errorf("invalid element type , it should be (*scriptInvokerPack) , but type is : %s)", reflect.TypeOf(res).String())
}
}
return result, nil
Expand Down
145 changes: 123 additions & 22 deletions cluster/router/script/instance/js_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
_ "github.com/dop251/goja_nodejs/console"
"github.com/dop251/goja_nodejs/require"
"github.com/stretchr/testify/assert"
"reflect"
"sync"
"testing"
)
Expand Down Expand Up @@ -110,7 +111,7 @@ func re_init_res_recv(runtime *goja.Runtime) {
}
}

func TestFuncImplByStructure(t *testing.T) {
func TestStructureFuncImpl(t *testing.T) {
runtime := goja.New()

test_invokers := []protocol.Invoker{protocol.NewBaseInvoker(url1())}
Expand Down Expand Up @@ -565,8 +566,43 @@ func setRunScriptEnv() *goja.Runtime {
}

func TestRunScriptInPanic(t *testing.T) {
rt := setRunScriptEnv()
const script = `(function route(invokers, invocation, context) {
willPanic := func(errScript string) {
rt := setRunScriptEnv()
pg, err := goja.Compile(``, errScript, true)
assert.Nil(t, err)
res, err := func() (res interface{}, err error) {
defer func(err *error) {
panicReason := recover()
if panicReason != nil {
switch panicReason.(type) {
case string:
*err = fmt.Errorf("panic: %s", panicReason.(string))
case error:
*err = panicReason.(error)
default:
*err = fmt.Errorf("panic occurred: failed to retrieve panic information. Expected string or error, got %T", panicReason)
}
}
}(&err)
res, err = rt.RunProgram(pg)
testData := res.(*goja.Object).Export()
assert.Equal(t, reflect.ValueOf([]interface{}{}), reflect.ValueOf(testData))
return
}()
assert.NotNil(t, err)
assert.Nil(t, res)
}
wontPanic := func(errScript string) {
rt := setRunScriptEnv()
pg, err := goja.Compile(``, errScript, true)
assert.Nil(t, err)
res, err := rt.RunProgram(pg)
assert.Nil(t, err)
assert.NotNil(t, res)
data := res.Export()
assert.NotNil(t, data)
}
const scriptInvokePanic = `(function route(invokers, invocation, context) {
var result = [];
for (var i = 0; i < invokers.length; i++) {
if ("127.0.0.1" === invokers[i].GetURL().Ip) {
Expand All @@ -581,23 +617,88 @@ func TestRunScriptInPanic(t *testing.T) {
return result;
}(invokers, invocation, context));
`
pg, err := goja.Compile(``, script, true)
assert.Nil(t, err)
res, err := func() (res interface{}, err error) {
defer func(err *error) {
panicReason := recover()
switch panicReason.(type) {
case string:
*err = fmt.Errorf("panic: %s", panicReason.(string))
case error:
*err = panicReason.(error)
default:
*err = fmt.Errorf("panic occurred: failed to retrieve panic information. Expected string or error, got %T", panicReason)
}
}(&err)
res, err = rt.RunProgram(pg)
return
}()
assert.NotNil(t, err)
assert.Nil(t, res)
willPanic(scriptInvokePanic)
const scriptNodeDestroyPanic = `(function route(invokers, invocation, context) {
var result = [];
for (var i = 0; i < invokers.length; i++) {
if ("127.0.0.1" === invokers[i].GetURL().Ip) {
if (invokers[i].GetURL().Port !== "20000") {
invokers[i].GetURL().Ip = "anotherIP"
// Destroy() call should go panic
invokers[i].Destroy()
result.push(invokers[i]);
}
}
}
return result;
}(invokers, invocation, context));
`
willPanic(scriptNodeDestroyPanic)

// Wrong Call will go panic , recover , and return an error
const scriptCallWrongFunc = `(function route(invokers, invocation, context) {
var result = [];
for (var i = 0; i < invokers.length; i++) {
if ("127.0.0.1" === invokers[i].GetURL().Ip) {
// err here
if (invokers[i].GetURLS(" Err Here ").Port !== "20000") {
invokers[i].GetURLS().Ip = "anotherIP"
result.push(invokers[i]);
}
}
}
return result;
}(invokers, invocation, context));
`
willPanic(scriptCallWrongFunc)

// these case means
// error input is program acceptable, but it will make an undefined error
const scriptCallWrongArgs1 = `(function route(invokers, invocation, context) {
var result = [];
for (var i = 0; i < invokers.length; i++) {
if ("127.0.0.1" === invokers[i].GetURL().Ip) {
if (invokers[i].GetURL(" Err Here ").Port !== "20000") {
//---------------------------------^ here wont go err , it will trans to ()
invokers[i].GetURL().Ip = "anotherIP"
result.push(invokers[i]);
}
}
}
return result;
}(invokers, invocation, context));
`
wontPanic(scriptCallWrongArgs1)

const scriptCallWrongArgs2 = `(function route(invokers, invocation, context) {
var result = [];
for (var i = 0; i < invokers.length; i++) {
if ("127.0.0.1" === invokers[i].GetURL().Ip) {
if (invokers[i].GetURL(" Err Here ").Port !== "20000") {
invokers[i].GetURL().AddParam( null , "key string", "value string")
//---------------------------------------------^ here wont go err , it will trans to ("" , "key string" , "value string")
result.push(invokers[i]);
}
}
}
return result;
}(invokers, invocation, context));
`
wontPanic(scriptCallWrongArgs2)

const scriptCallWrongArgs3 = `(function route(invokers, invocation, context) {
var result = [];
for (var i = 0; i < invokers.length; i++) {
if ("127.0.0.1" === invokers[i].GetURL().Ip) {
if (invokers[i].GetURL(" Err Here ").Port !== "20000") {
invokers[i].GetURL().AddParam( invocation , "key string", "value string")
//---------------------------------------------^ here wont go err , it will trans to ("[object Object]" , "key string" , "value string")
result.push(invokers[i]);
}
}
}
return result;
}(invokers, invocation, context));
`
wontPanic(scriptCallWrongArgs3)
}