From 240b6016dfc0ed55c0b51978a2c59ffbc5eeda21 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Sun, 14 Feb 2021 23:47:11 +0300 Subject: [PATCH] flow: add initial flow dag Signed-off-by: Vasiliy Tolstov --- flow/dag.go | 21 +++++++++++++++ flow/dag_test.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ flow/flow.go | 7 +++++ go.mod | 2 ++ go.sum | 10 ++++--- 5 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 flow/dag.go create mode 100644 flow/dag_test.go create mode 100644 flow/flow.go diff --git a/flow/dag.go b/flow/dag.go new file mode 100644 index 00000000..4cc728ea --- /dev/null +++ b/flow/dag.go @@ -0,0 +1,21 @@ +package flow + +type node struct { + name string +} + +func (n *node) ID() string { + return n.name +} + +func (n *node) Name() string { + return n.name +} + +func (n *node) String() string { + return n.name +} + +func (n *node) Hashcode() interface{} { + return n.name +} diff --git a/flow/dag_test.go b/flow/dag_test.go new file mode 100644 index 00000000..bddd412d --- /dev/null +++ b/flow/dag_test.go @@ -0,0 +1,68 @@ +package flow + +import ( + "fmt" + "testing" + + "github.com/silas/dag" +) + +func checkErr(t *testing.T, err error) { + if err != nil { + t.Fatal(err) + } +} + +func TestDag(t *testing.T) { + d1 := &dag.AcyclicGraph{} + d2 := &dag.AcyclicGraph{} + d2v1 := d2.Add(&node{"Substep.Create"}) + v1 := d1.Add(&node{"AccountService.Create"}) + v2 := d1.Add(&node{"AuthzService.Create"}) + v3 := d1.Add(&node{"AuthnService.Create"}) + v4 := d1.Add(&node{"ProjectService.Create"}) + v5 := d1.Add(&node{"ContactService.Create"}) + v6 := d1.Add(&node{"NetworkService.Create"}) + v7 := d1.Add(&node{"MailerService.Create"}) + v8 := d1.Add(&node{"NestedService.Create"}) + v9 := d1.Add(d2v1) + d1.Connect(dag.BasicEdge(v1, v2)) + d1.Connect(dag.BasicEdge(v1, v3)) + d1.Connect(dag.BasicEdge(v1, v4)) + d1.Connect(dag.BasicEdge(v1, v5)) + d1.Connect(dag.BasicEdge(v1, v6)) + d1.Connect(dag.BasicEdge(v1, v7)) + d1.Connect(dag.BasicEdge(v7, v8)) + d1.Connect(dag.BasicEdge(v8, v9)) + + if err := d1.Validate(); err != nil { + t.Fatal(err) + } + + d1.TransitiveReduction() + + var steps [][]string + fn := func(n dag.Vertex, idx int) error { + if idx == 0 { + steps = make([][]string, 1, 1) + steps[0] = make([]string, 0, 1) + } else if idx >= len(steps) { + tsteps := make([][]string, idx+1, idx+1) + copy(tsteps, steps) + steps = tsteps + steps[idx] = make([]string, 0, 1) + } + steps[idx] = append(steps[idx], fmt.Sprintf("%s", n)) + return nil + } + + start := &node{"AccountService.Create"} + err := d1.SortedDepthFirstWalk([]dag.Vertex{start}, fn) + checkErr(t, err) + if len(steps) != 4 { + t.Fatalf("invalid steps: %#+v", steps) + } + if steps[3][0] != "Substep.Create" { + t.Fatalf("invalid last step: %#+v", steps) + } +} diff --git a/flow/flow.go b/flow/flow.go new file mode 100644 index 00000000..df8054dc --- /dev/null +++ b/flow/flow.go @@ -0,0 +1,7 @@ +// Package flow is an interface used for saga pattern messaging +package flow + +type Step interface { + // Endpoint returns service_name.service_method + Endpoint() string +} diff --git a/go.mod b/go.mod index 6ddf07b5..6542789a 100644 --- a/go.mod +++ b/go.mod @@ -6,10 +6,12 @@ require ( github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/ef-ds/deque v1.0.4 github.com/google/uuid v1.2.0 + github.com/heimdalr/dag v1.0.1 // indirect github.com/imdario/mergo v0.3.11 github.com/kr/text v0.2.0 // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/patrickmn/go-cache v2.1.0+incompatible + github.com/silas/dag v0.0.0-20210121180416-41cf55125c34 // indirect golang.org/x/net v0.0.0-20210119194325-5f4716e94777 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect ) diff --git a/go.sum b/go.sum index 9d5305e9..d4ec987d 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,13 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/ef-ds/deque v1.0.4 h1:iFAZNmveMT9WERAkqLJ+oaABF9AcVQ5AjXem/hroniI= github.com/ef-ds/deque v1.0.4/go.mod h1:gXDnTC3yqvBcHbq2lcExjtAcVrOnJCbMcZXmuj8Z4tg= +github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= +github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/heimdalr/dag v1.0.1 h1:iR2K3DSUFDYx0GeV7iXBnZkedWS1xePSGrylQ197uxg= +github.com/heimdalr/dag v1.0.1/go.mod h1:t+ZkR+sjKL4xhlE1B9rwpvwfo+x+2R0363efS+Oghns= github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -15,13 +20,12 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/unistack-org/micro v1.18.0 h1:EbFiII0bKV0Xcua7o6J30MFmm4/g0Hv3ECOKzsUBihU= +github.com/silas/dag v0.0.0-20210121180416-41cf55125c34 h1:vBfVmA5mZhsQa2jr1FOL9nfA37N/jnbBmi5XUfviVTI= +github.com/silas/dag v0.0.0-20210121180416-41cf55125c34/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I= golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=