3
0
Files
corteza/pkg/envoy/builder.go
Tomaž Jerman 10b300328d Implement data shaping
Unstructured datasources (csv, jsonl, ...) are defined as resource
datasets.
These datasets are then "shaped" based on some template.

The result is an envoy resource like any other.
2020-11-27 11:19:16 +01:00

116 lines
2.1 KiB
Go

package envoy
import (
"context"
"github.com/cortezaproject/corteza-server/pkg/envoy/resource"
)
type (
builder struct {
pp []Preparer
}
// Rc is an alias for the ResourceState channel
Rc chan *ResourceState
Preparer interface {
Prepare(ctx context.Context, ee ...*ResourceState) error
}
// Encoder encodes all resources provided by the Rc until nil is passed
//
// Encoding errors are passed via Ec.
Encoder interface {
Encode(ctx context.Context, p Provider) error
}
PrepareEncoder interface {
Preparer
Encoder
}
)
func NewBuilder(pp ...Preparer) *builder {
return &builder{
pp: pp,
}
}
func (b *builder) Build(ctx context.Context, rr ...resource.Interface) (*graph, error) {
g := newGraph()
// Prepare nodes for all resources
nn := make(nodeSet, 0, len(rr))
for _, r := range rr {
nn = nn.add(newNode(r))
}
// Let's keep track of the missing deps.
mMap := make(map[resource.Interface]resource.RefSet)
// Index all resources for nicer lookups
nIndex := make(nodeIndex)
nIndex.Add(nn...)
// Build the graph
for _, cNode := range nn {
refs := cNode.res.Refs()
missingRefs := make(resource.RefSet, 0, len(refs))
// Attempt to connect all available nodes
for _, ref := range refs {
rNode := nIndex.GetRef(ref)
if rNode == nil {
missingRefs = append(missingRefs, ref)
continue
}
// The resource is available; we can connect the two
g.addChild(cNode, rNode)
g.addParent(rNode, cNode)
}
g.addNode(cNode)
if len(missingRefs) > 0 {
mMap[cNode.res] = missingRefs
}
}
// Do any dep. related preprocessing
var state *ResourceState
var err error
err = func() error {
for {
state, err = g.NextInverted(ctx)
if err != nil {
return err
} else if state == nil {
return nil
}
// Copy state so we don't alter the original one
nState := state
nState.MissingDeps = mMap[state.Res]
for _, p := range b.pp {
err = p.Prepare(ctx, nState)
if err != nil {
return err
}
}
}
}()
if err != nil {
return nil, err
}
g.Relink()
g.reset()
return g, nil
}