SSE: Localize/Contain Errors within an Expression (#73163)
Changes SSE to not always fail all queries when one fails. Now only the query itself, and nodes that depend on it will error. --------- Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com>
This commit is contained in:
co-authored by
Gilles De Mey
parent
01755608db
commit
35e488b22b
+35
-9
@@ -44,8 +44,13 @@ type Node interface {
|
||||
ID() int64 // ID() allows the gonum graph node interface to be fulfilled
|
||||
NodeType() NodeType
|
||||
RefID() string
|
||||
Execute(ctx context.Context, now time.Time, vars mathexp.Vars, s *Service) (mathexp.Results, error)
|
||||
String() string
|
||||
NeedsVars() []string
|
||||
}
|
||||
|
||||
type ExecutableNode interface {
|
||||
Node
|
||||
Execute(ctx context.Context, now time.Time, vars mathexp.Vars, s *Service) (mathexp.Results, error)
|
||||
}
|
||||
|
||||
// DataPipeline is an ordered set of nodes returned from DPGraph processing.
|
||||
@@ -67,27 +72,48 @@ func (dp *DataPipeline) execute(c context.Context, now time.Time, s *Service) (m
|
||||
dsNodes = append(dsNodes, node.(*DSNode))
|
||||
}
|
||||
|
||||
if err := executeDSNodesGrouped(c, now, vars, s, dsNodes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
executeDSNodesGrouped(c, now, vars, s, dsNodes)
|
||||
}
|
||||
|
||||
for _, node := range *dp {
|
||||
if groupByDSFlag && node.NodeType() == TypeDatasourceNode {
|
||||
continue // already executed via executeDSNodesGrouped
|
||||
}
|
||||
|
||||
// Don't execute nodes that have dependent nodes that have failed
|
||||
var hasDepError bool
|
||||
for _, neededVar := range node.NeedsVars() {
|
||||
if res, ok := vars[neededVar]; ok {
|
||||
if res.Error != nil {
|
||||
errResult := mathexp.Results{
|
||||
Error: makeDependencyError(node.RefID(), neededVar),
|
||||
}
|
||||
vars[node.RefID()] = errResult
|
||||
hasDepError = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if hasDepError {
|
||||
continue
|
||||
}
|
||||
|
||||
c, span := s.tracer.Start(c, "SSE.ExecuteNode")
|
||||
span.SetAttributes("node.refId", node.RefID(), attribute.Key("node.refId").String(node.RefID()))
|
||||
if node.NodeType() == TypeCMDNode {
|
||||
cmdNode := node.(*CMDNode)
|
||||
inputRefIDs := cmdNode.Command.NeedsVars()
|
||||
if len(node.NeedsVars()) > 0 {
|
||||
inputRefIDs := node.NeedsVars()
|
||||
span.SetAttributes("node.inputRefIDs", inputRefIDs, attribute.Key("node.inputRefIDs").StringSlice(inputRefIDs))
|
||||
}
|
||||
defer span.End()
|
||||
|
||||
res, err := node.Execute(c, now, vars, s)
|
||||
execNode, ok := node.(ExecutableNode)
|
||||
if !ok {
|
||||
return vars, makeUnexpectedNodeTypeError(node.RefID(), node.NodeType().String())
|
||||
}
|
||||
|
||||
res, err := execNode.Execute(c, now, vars, s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
res.Error = err
|
||||
}
|
||||
|
||||
vars[node.RefID()] = res
|
||||
|
||||
Reference in New Issue
Block a user