jhole89/orbital

View on GitHub
app/database/gremlin.go

Summary

Maintainability
A
0 mins
Test Coverage
package database

import (
    "github.com/northwesternmutual/grammes"
    "github.com/northwesternmutual/grammes/model"
    "github.com/northwesternmutual/grammes/query"
    "log"
    "strings"
    "time"
)

type Gremlin struct {
    Client gremlinClient
}

type gremlinClient interface {
    AddVertex(label string, properties ...interface{}) (model.Vertex, error)
    AllVertices() ([]model.Vertex, error)
    DropAll() error
    ExecuteQuery(queryObj query.Query) ([][]byte, error)
}

func newGremlin(dsn string) (Graph, error) {

    errs := make(chan error)
    go func(chan error) {
        err := <-errs
        log.Printf("Lost connection to the database: %s\n", err.Error())
    }(errs)

    retryCount := 10
    for {
        log.Println("Connecting to Gremlin database at: " + dsn)
        conn, err := grammes.DialWithWebSocket(dsn, grammes.WithErrorChannel(errs))
        if err != nil {
            if retryCount == 0 {
                log.Println("Unable to connect to Gremlin database at: " + dsn)
                return &Gremlin{}, err
            }

            log.Printf("Could not connect to Gremlin server. Wait 2 seconds. %d retries left...\n", retryCount)
            retryCount--
            time.Sleep(2 * time.Second)
        } else {
            log.Println("Connected to Gremlin database at: " + dsn)
            return &Gremlin{Client: conn}, nil
        }
    }
}

func (g *Gremlin) Clean() error {
    err := g.Client.DropAll()
    if err != nil {
        return err
    }
    log.Println("All vertices deleted, database is now empty.")
    return nil
}

func (g *Gremlin) CreateEntity(e *Entity) (*Entity, error) {
    vertex, err := g.Client.AddVertex(e.Context, "name", e.Name, "context", e.Context)
    if err != nil {
        return &Entity{}, err
    }
    ent, err := g.GetEntity(vertex.ID())
    if err != nil {
        return &Entity{}, err
    }
    log.Printf("Created Entity: {ID: %v, Name: %s, Context: %s}\n", ent.ID, ent.Name, ent.Context)
    return ent, nil
}

func (g *Gremlin) CreateRelationship(r *Relationship) (*Relationship, error) {
    t := grammes.Traversal()
    resp, err := g.Client.ExecuteQuery(t.AddE(r.Context).From(t.V(r.From.ID)).To(t.V(r.To.ID)))
    if err != nil {
        return &Relationship{}, err
    }
    edges, err := grammes.UnmarshalEdgeList(resp)
    if err != nil {
        return &Relationship{}, err
    }
    r.ID = edges[0].ID()

    log.Printf("Created Relationship: {ID: %v, Context: %s, From: %s (ID: %v), To: %s (ID: %v)}\n", r.ID, r.Context, r.From.Name, r.From.ID, r.To.Name, r.To.ID)
    return r, nil
}

func (g *Gremlin) GetEntity(id interface{}) (*Entity, error) {
    resp, err := g.Client.ExecuteQuery(grammes.Traversal().V(id).Properties())
    if err != nil {
        return &Entity{}, err
    }

    var e = Entity{ID: id}

    props, err := grammes.UnmarshalPropertyList(resp)
    if err != nil {
        return &Entity{}, err
    }

    for _, p := range props {
        v := p.GetValue().(string)
        switch strings.ToLower(p.Value.Label) {
        case "name":
            e.Name = v
        case "context":
            e.Context = v
        }
    }
    return &e, nil
}

func (g *Gremlin) GetRelationships(id interface{}, context string) ([]*Entity, error) {
    var entities []*Entity
    resp, err := g.Client.ExecuteQuery(grammes.Traversal().V(id).Out(context))
    if err != nil {
        return entities, err
    }
    vertices, err := grammes.UnmarshalVertexList(resp)
    if err != nil {
        return entities, err
    }
    for _, v := range vertices {
        ent, err := g.GetEntity(v.ID())
        if err != nil {
            return entities, err
        }
        entities = append(entities, ent)
    }
    return entities, nil
}

func (g *Gremlin) ListEntities() ([]*Entity, error) {
    vertices, err := g.Client.AllVertices()
    var entities []*Entity
    if err != nil {
        return entities, err
    }

    for _, ent := range vertices {
        entity, err := g.GetEntity(ent.ID())
        if err != nil {
            return entities, err
        }
        entities = append(entities, entity)
    }
    return entities, nil
}