Skip to content

Commit

Permalink
feat: wip! dump links
Browse files Browse the repository at this point in the history
  • Loading branch information
adrienaury committed Mar 21, 2024
1 parent 8dd732a commit 085fd37
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 23 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/cgi-fr/silo
go 1.21

require (
github.com/dominikbraun/graph v0.23.0
github.com/rs/zerolog v1.28.0
github.com/stretchr/testify v1.9.0
)
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dominikbraun/graph v0.23.0 h1:TdZB4pPqCLFxYhdyMFb1TBdFxp8XLcJfTTBQucVPgCo=
github.com/dominikbraun/graph v0.23.0/go.mod h1:yOjYyogZLY1LSG9E33JWZJiq5k83Qy2C6POAuiViluc=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
Expand Down
5 changes: 5 additions & 0 deletions pkg/silo/driven.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,8 @@ type Backend interface {
ReadLinks() DataLinkReader
ReadNodes() DataNodeReader
}

type DumpWriter interface {
Write(node DataNode, uuid string) error
Close() error
}
80 changes: 58 additions & 22 deletions pkg/silo/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,52 @@ import (
"errors"
"fmt"
"io"

"github.com/dominikbraun/graph"
)

type Driver struct {
backend Backend
writer DumpWriter
}

func NewDriver(backend Backend) *Driver {
func NewDriver(backend Backend, writer DumpWriter) *Driver {
return &Driver{
backend: backend,
writer: writer,
}
}

func (d *Driver) Dump() error {
nodes, _ := d.ReadAllNodes()
links, _ := d.ReadAllLinks()

grph := graph.New[string, DataNode](func(n DataNode) string { return n.String() }, graph.Directed())

for _, node := range nodes {
if err := grph.AddVertex(node); err != nil {
return fmt.Errorf("%w", err)
}
}

for _, link := range links {
if err := grph.AddEdge(link.E1.String(), link.E2.String()); err != nil {
return fmt.Errorf("%w", err)
}
}

result, err := graph.StronglyConnectedComponents[string, DataNode](grph)
if err != nil {
return fmt.Errorf("%w", err)
}

for i, component := range result {
for _, id := range component {
println(i, id)
}
}

return nil
}

func (d *Driver) Scan(input DataRowReader) error {
Expand All @@ -46,7 +82,7 @@ func (d *Driver) Scan(input DataRowReader) error {
break
}

nodes, links := scan(datarow)
nodes, links := Scan(datarow)

for _, node := range nodes {
if err := d.backend.StoreNode(node); err != nil {
Expand All @@ -64,26 +100,6 @@ func (d *Driver) Scan(input DataRowReader) error {
return nil
}

func scan(datarow DataRow) ([]DataNode, []DataLink) {
nodes := []DataNode{}
links := []DataLink{}

for key, value := range datarow {
if value != nil {
nodes = append(nodes, DataNode{Key: key, Data: value})
}
}

// find all pairs in nodes
for i := 0; i < len(nodes); i++ {
for j := i + 1; j < len(nodes); j++ {
links = append(links, DataLink{E1: nodes[i], E2: nodes[j]})
}
}

return nodes, links
}

func (d *Driver) ReadAllNodes() ([]DataNode, error) {
nodes := []DataNode{}
reader := d.backend.ReadNodes()
Expand Down Expand Up @@ -123,3 +139,23 @@ func (d *Driver) ReadAllLinks() ([]DataLink, error) {

return links, nil
}

func Scan(datarow DataRow) ([]DataNode, []DataLink) {
nodes := []DataNode{}
links := []DataLink{}

for key, value := range datarow {
if value != nil {
nodes = append(nodes, DataNode{Key: key, Data: value})
}
}

// find all pairs in nodes
for i := 0; i < len(nodes); i++ {
for j := i + 1; j < len(nodes); j++ {
links = append(links, DataLink{E1: nodes[i], E2: nodes[j]})
}
}

return nodes, links
}
52 changes: 51 additions & 1 deletion pkg/silo/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestNominal(t *testing.T) {
input := silo.NewDataRowReaderInMemory(rows)

backend := silo.NewBackendInMemory()
driver := silo.NewDriver(backend)
driver := silo.NewDriver(backend, nil)

err := driver.Scan(input)
require.NoError(t, err)
Expand All @@ -47,4 +47,54 @@ func TestNominal(t *testing.T) {
links, err := driver.ReadAllLinks()
require.NoError(t, err)
assert.Len(t, links, 12)

require.NoError(t, driver.Dump())
}

func TestPartialNull(t *testing.T) {
t.Parallel()

rows := []silo.DataRow{
{"ID1": 1, "ID2": nil, "ID3": nil, "ID4": "00001"},
{"ID1": nil, "ID2": "2", "ID3": 2.0, "ID4": nil},
}
input := silo.NewDataRowReaderInMemory(rows)

backend := silo.NewBackendInMemory()
driver := silo.NewDriver(backend, nil)

err := driver.Scan(input)
require.NoError(t, err)

nodes, err := driver.ReadAllNodes()
require.NoError(t, err)
assert.Len(t, nodes, 4)

links, err := driver.ReadAllLinks()
require.NoError(t, err)
assert.Len(t, links, 2)
}

func TestPartialMissing(t *testing.T) {
t.Parallel()

rows := []silo.DataRow{
{"ID1": 1, "ID4": "00001"},
{"ID2": "2", "ID3": 2.0},
}
input := silo.NewDataRowReaderInMemory(rows)

backend := silo.NewBackendInMemory()
driver := silo.NewDriver(backend, nil)

err := driver.Scan(input)
require.NoError(t, err)

nodes, err := driver.ReadAllNodes()
require.NoError(t, err)
assert.Len(t, nodes, 4)

links, err := driver.ReadAllLinks()
require.NoError(t, err)
assert.Len(t, links, 2)
}
60 changes: 60 additions & 0 deletions pkg/silo/graph.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (C) 2024 CGI France
//
// This file is part of SILO.
//
// SILO is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// SILO is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SILO. If not, see <http://www.gnu.org/licenses/>.

package silo

import (
"encoding/json"
"fmt"
"strconv"
"strings"
)

func toStringRepresentationBuffered(value any, stringbuffer *strings.Builder) {
switch tvalue := value.(type) {
case string:
stringbuffer.WriteString("string(")
stringbuffer.WriteString(tvalue)
stringbuffer.WriteByte(')')
case bool:
stringbuffer.WriteString("bool(")
stringbuffer.WriteString(strconv.FormatBool(tvalue))
stringbuffer.WriteByte(')')
case float64:
stringbuffer.WriteString("number(")
stringbuffer.WriteString(strconv.FormatFloat(tvalue, 'g', -1, 64))
stringbuffer.WriteByte(')')
case int, int64, int32, int16, int8, uint, uint64, uint32, uint16, uint8:
stringbuffer.WriteString("number(")
stringbuffer.WriteString(fmt.Sprint(tvalue))
stringbuffer.WriteByte(')')
case json.Number:
stringbuffer.WriteString("number(")
stringbuffer.WriteString(string(tvalue))
stringbuffer.WriteByte(')')
case []any:
stringbuffer.WriteString("slice(")

for _, value := range tvalue {
toStringRepresentationBuffered(value, stringbuffer)
}

stringbuffer.WriteByte(')')
case nil:
stringbuffer.WriteString("nil(nil)")
}
}
14 changes: 14 additions & 0 deletions pkg/silo/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package silo

import "strings"

type DataRow map[string]any

type DataNode struct {
Expand All @@ -28,3 +30,15 @@ type DataLink struct {
E1 DataNode
E2 DataNode
}

func (n DataNode) String() string {
result := &strings.Builder{}
result.Grow(512) //nolint:gomnd

result.WriteString(n.Key)
result.WriteRune('=')

toStringRepresentationBuffered(n.Data, result)

return result.String()
}

0 comments on commit 085fd37

Please sign in to comment.