marsevilspirit commented on code in PR #788: URL: https://github.com/apache/incubator-seata-go/pull/788#discussion_r1988221616
########## pkg/saga/statemachine/engine/expr/expression_resolver_test.go: ########## @@ -0,0 +1,59 @@ +package expr + +import ( + "fmt" Review Comment: delete fmt ########## pkg/saga/statemachine/engine/expr/expression_resolver_test.go: ########## @@ -0,0 +1,59 @@ +package expr + +import ( + "fmt" Review Comment: done ########## pkg/saga/statemachine/engine/expr/expression_factory_manager.go: ########## @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package expr + +import "strings" + +const DefaultExpressionType string = "Default" Review Comment: done ########## pkg/saga/statemachine/engine/expr/expression_resolver.go: ########## @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package expr + +import ( + "errors" + "strings" +) + +type ExpressionResolver interface { + Expression(expressionStr string) Expression + ExpressionFactoryManager() ExpressionFactoryManager + SetExpressionFactoryManager(expressionFactoryManager ExpressionFactoryManager) +} + +type DefaultExpressionResolver struct { + expressionFactoryManager ExpressionFactoryManager +} + +func (resolver *DefaultExpressionResolver) Expression(expressionStr string) Expression { Review Comment: done ########## pkg/saga/statemachine/engine/expr/cel_expression.go: ########## @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package expr + +import ( + "github.com/google/cel-go/cel" + "github.com/google/cel-go/common/decls" +) + +type CELExpression struct { + env *cel.Env + program cel.Program + expression string +} + +// This is used to make sure that the CELExpression implements the Expression interface. +var _ Expression = (*CELExpression)(nil) + +// NewCELExpression creates a new CELExpression instance +// by compiling the provided expression. +// how to use cel: https://codelabs.developers.google.com/codelabs/cel-go +func NewCELExpression(expression string) (*CELExpression, error) { + // Create the standard environment. + env, err := cel.NewEnv( + cel.VariableDecls( + decls.NewVariable("elContext", cel.DynType), + ), + ) + + if err != nil { + return nil, err + } + + // Check that the expression compiles and returns a String. + ast, issues := env.Compile(expression) + // Report syntax errors, if present. + if issues != nil && issues.Err() != nil { + return nil, issues.Err() + } + + // Type-check the expression ofr correctness. + checkedAst, issues := env.Check(ast) + if issues.Err() != nil { + return nil, issues.Err() + } + + program, err := env.Program(checkedAst) + if err != nil { + return nil, err + } + + CELExpression := &CELExpression{ + env: env, + program: program, + expression: expression, + } + + return CELExpression, nil +} + +// Value evaluates the expression with the provided context and returns the result. +func (c *CELExpression) Value(elContext any) any { + result, _, err := c.program.Eval(map[string]any{ + "elContext": elContext, + }) + if err != nil { + return err + } + return result.Value() +} + +// TODO: I think this is not needed. +// I see seata-java doesn't use this method. +// Do we need to implement this? +func (c *CELExpression) SetValue(val any, elContext any) { + panic("implement me") Review Comment: SetValue is a interface for expression, so we should implement this funcion. ########## pkg/saga/statemachine/engine/expr/expression_resolver_test.go: ########## @@ -0,0 +1,59 @@ +package expr + +import ( + "fmt" + "testing" +) + +func TestParseExpressionStruct(t *testing.T) { + tests := []struct { + expressionStr string + expected *ExpressionStruct + expectError bool + }{ + { + expressionStr: "$type{content}", + expected: &ExpressionStruct{ + typeStart: 0, + typeEnd: 5, + typ: "type", + end: 13, + content: "content", + }, + expectError: false, + }, + { + expressionStr: "$type.content", + expected: &ExpressionStruct{ + typeStart: 0, + typeEnd: 5, + typ: "type", + end: 13, + content: "content", + }, + expectError: false, + }, + { + expressionStr: "invalid expression", + expected: nil, + expectError: true, + }, + } + + for _, test := range tests { + result, err := parseExpressionStruct(test.expressionStr) + + if (err != nil) != test.expectError { Review Comment: done ########## pkg/saga/statemachine/engine/expr/expression_resolver.go: ########## @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package expr + +import ( + "errors" + "strings" +) + +type ExpressionResolver interface { + Expression(expressionStr string) Expression + ExpressionFactoryManager() ExpressionFactoryManager + SetExpressionFactoryManager(expressionFactoryManager ExpressionFactoryManager) +} + +type DefaultExpressionResolver struct { + expressionFactoryManager ExpressionFactoryManager +} + +func (resolver *DefaultExpressionResolver) Expression(expressionStr string) Expression { + expressionStruct, err := parseExpressionStruct(expressionStr) + if err != nil { + return nil + } + expressionFactory := resolver.expressionFactoryManager.GetExpressionFactory(expressionStruct.typ) + if expressionFactory == nil { + return nil + } + return expressionFactory.CreateExpression(expressionStruct.content) +} + +func (resolver *DefaultExpressionResolver) ExpressionFactoryManager() ExpressionFactoryManager { + return resolver.expressionFactoryManager +} + +func (resolver *DefaultExpressionResolver) SetExpressionFactoryManager(expressionFactoryManager ExpressionFactoryManager) { + resolver.expressionFactoryManager = expressionFactoryManager +} + +type ExpressionStruct struct { + typeStart int + typeEnd int + end int + typ string + content string +} + +// old style: $type{content} Review Comment: I see that seata-java has two styles: old style and new style. https://github.com/apache/incubator-seata/blob/886874e26eb5ade85f45c65c147c056b7baeb08a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/expression/impl/DefaultExpressionResolver.java#L62 ########## go.mod: ########## @@ -1,6 +1,8 @@ module github.com/seata/seata-go -go 1.18 +go 1.23.0 Review Comment: fixed ########## pkg/saga/statemachine/engine/expr/cel_expression_test.go: ########## @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package expr + +import ( + "testing" +) + +func TestValueWithNil(t *testing.T) { + expr, err := NewCELExpression("'Hello' + ' World!'") + if err != nil { + t.Error("Error creating expression:", err) + return + } + value := expr.Value(nil) + if value != "Hello World!" { Review Comment: done -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: notifications-unsubscr...@seata.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@seata.apache.org For additional commands, e-mail: notifications-h...@seata.apache.org