From 9b165112394cacaba48c3288d8e89579c5ab7630 Mon Sep 17 00:00:00 2001
From: thijsheijden <hi@thijsheijden.nl>
Date: Tue, 18 May 2021 13:30:17 +0200
Subject: [PATCH] Moved request sender into external package

---
 cmd/query-service/main.go                     |   6 +-
 go.mod                                        |   3 +-
 go.sum                                        |   8 +
 internal/usecases/consume/consume.go          |   8 +-
 internal/usecases/consume/consume_test.go     |  34 ++--
 internal/usecases/consume/handlemessage.go    |   2 +-
 internal/usecases/request/interface.go        |   6 -
 .../request/mockrequest/mockrequest.go        |  33 ----
 internal/usecases/request/request.go          | 174 ------------------
 internal/usecases/request/requestStructs.go   |  10 -
 10 files changed, 35 insertions(+), 249 deletions(-)
 delete mode 100644 internal/usecases/request/interface.go
 delete mode 100644 internal/usecases/request/mockrequest/mockrequest.go
 delete mode 100644 internal/usecases/request/request.go
 delete mode 100644 internal/usecases/request/requestStructs.go

diff --git a/cmd/query-service/main.go b/cmd/query-service/main.go
index 987f019..ecb466b 100644
--- a/cmd/query-service/main.go
+++ b/cmd/query-service/main.go
@@ -5,12 +5,12 @@ import (
 	"query-service/internal/usecases/consume"
 	"query-service/internal/usecases/databaseinfo"
 	"query-service/internal/usecases/produce"
-	"query-service/internal/usecases/request"
 	"query-service/pkg/logger"
 
 	"git.science.uu.nl/datastrophe/broker"
 	"git.science.uu.nl/datastrophe/keyvaluestore"
 	"git.science.uu.nl/datastrophe/query-conversion/aql"
+	"git.science.uu.nl/datastrophe/query-execution/arangodb"
 	"github.com/thijsheijden/alice"
 )
 
@@ -33,11 +33,11 @@ func main() {
 	// MARK: Create relevant services for consuming a message
 	convertQueryService := aql.NewService()
 
-	requestSenderService := request.NewService()
+	requestSender := arangodb.NewService()
 
 	databaseInfoService := databaseinfo.NewService(rpcDriver)
 
-	consumeService := consume.NewService(broker, produceService, convertQueryService, requestSenderService, databaseInfoService)
+	consumeService := consume.NewService(broker, produceService, convertQueryService, requestSender, databaseInfoService)
 
 	// MARK: Start services
 	keyValueStore.Connect()
diff --git a/go.mod b/go.mod
index 237510f..485ef68 100644
--- a/go.mod
+++ b/go.mod
@@ -6,6 +6,7 @@ require (
 	git.science.uu.nl/datastrophe/broker v0.0.0-20210516094125-abbeaf96fd58
 	git.science.uu.nl/datastrophe/keyvaluestore v0.0.0-20210517170603-34902cd5c90d
 	git.science.uu.nl/datastrophe/query-conversion v0.0.0-20210518093948-06ff65cdf577
+	git.science.uu.nl/datastrophe/query-execution v0.0.0-20210518112715-043c7046dc7b
 	github.com/arangodb/go-driver v0.0.0-20210518064911-4985e8be3d90
 	github.com/boumenot/gocover-cobertura v1.1.0 // indirect
 	github.com/stretchr/testify v1.7.0
@@ -14,6 +15,6 @@ require (
 	golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
 	golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 // indirect
 	golang.org/x/tools v0.1.1 // indirect
-	google.golang.org/grpc v1.37.0
+	google.golang.org/grpc v1.37.1
 	google.golang.org/protobuf v1.26.0
 )
diff --git a/go.sum b/go.sum
index eed7e87..c52b3df 100644
--- a/go.sum
+++ b/go.sum
@@ -11,6 +11,14 @@ git.science.uu.nl/datastrophe/query-conversion v0.0.0-20210518093728-9ee791a5281
 git.science.uu.nl/datastrophe/query-conversion v0.0.0-20210518093728-9ee791a5281e/go.mod h1:6rvalwekoukmVu3SbWmZkj8wBZEm34wDbA4Ilxcb+jw=
 git.science.uu.nl/datastrophe/query-conversion v0.0.0-20210518093948-06ff65cdf577 h1:Xd9hpnnRhYWdAXzLFviA6fYWnQoFD/4NtzmEC7Ntc/U=
 git.science.uu.nl/datastrophe/query-conversion v0.0.0-20210518093948-06ff65cdf577/go.mod h1:6rvalwekoukmVu3SbWmZkj8wBZEm34wDbA4Ilxcb+jw=
+git.science.uu.nl/datastrophe/query-execution v0.0.0-20210518111902-8bcfa627876b h1:39vY4lrkwKjk0SjsysegghrLMRGmpdu0/HwmNLfKDhI=
+git.science.uu.nl/datastrophe/query-execution v0.0.0-20210518111902-8bcfa627876b/go.mod h1:4YfKaCyadGlmAVbKOa6J2E2H56T7+RTF7xVCmcTCwmM=
+git.science.uu.nl/datastrophe/query-execution v0.0.0-20210518112126-ffe0684babaf h1:9Zkb/ZsTI4Nf9QRGXUShElMK8MnA9dWzS32Gs/azv7M=
+git.science.uu.nl/datastrophe/query-execution v0.0.0-20210518112126-ffe0684babaf/go.mod h1:4YfKaCyadGlmAVbKOa6J2E2H56T7+RTF7xVCmcTCwmM=
+git.science.uu.nl/datastrophe/query-execution v0.0.0-20210518112422-120f15c7bbd9 h1:uUkLULN8WTFk4jBQQsF0yoe8Odg7SEpCOH2ouh8rfUA=
+git.science.uu.nl/datastrophe/query-execution v0.0.0-20210518112422-120f15c7bbd9/go.mod h1:4YfKaCyadGlmAVbKOa6J2E2H56T7+RTF7xVCmcTCwmM=
+git.science.uu.nl/datastrophe/query-execution v0.0.0-20210518112715-043c7046dc7b h1:mEuRIwUfpblTbk9DMkGwlD66bV7VSyCGXW+lgqGCoF8=
+git.science.uu.nl/datastrophe/query-execution v0.0.0-20210518112715-043c7046dc7b/go.mod h1:4YfKaCyadGlmAVbKOa6J2E2H56T7+RTF7xVCmcTCwmM=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/arangodb/go-driver v0.0.0-20210506071742-64f314d85db7 h1:xRFEg4kM17h2fIOt3o4+mws3uRpw5rqWtemPYKfTURg=
 github.com/arangodb/go-driver v0.0.0-20210506071742-64f314d85db7/go.mod h1:3NUekcRLpgheFIGEwcOvxilEW73MV1queNKW58k7sdc=
diff --git a/internal/usecases/consume/consume.go b/internal/usecases/consume/consume.go
index dc1974e..446030d 100644
--- a/internal/usecases/consume/consume.go
+++ b/internal/usecases/consume/consume.go
@@ -3,10 +3,10 @@ package consume
 import (
 	"query-service/internal/usecases/databaseinfo"
 	"query-service/internal/usecases/produce"
-	"query-service/internal/usecases/request"
 
 	"git.science.uu.nl/datastrophe/broker"
 	"git.science.uu.nl/datastrophe/query-conversion"
+	queryexecution "git.science.uu.nl/datastrophe/query-execution"
 )
 
 // Service wraps consumer methods
@@ -15,17 +15,17 @@ type Service struct {
 	brokerDriver        broker.Interface
 	producer            produce.UseCase
 	queryConverter      query.Converter
-	requestSender       request.UseCase
+	requestSender       queryexecution.Executor
 	databaseInfoService databaseinfo.UseCase
 }
 
 // NewService creates a new service
-func NewService(broker broker.Interface, produceService produce.UseCase, queryConverter query.Converter, requestSenderService request.UseCase, databaseInfoService databaseinfo.UseCase) *Service {
+func NewService(broker broker.Interface, produceService produce.UseCase, queryConverter query.Converter, requestSender queryexecution.Executor, databaseInfoService databaseinfo.UseCase) *Service {
 	return &Service{
 		brokerDriver:        broker,
 		producer:            produceService,
 		queryConverter:      queryConverter,
-		requestSender:       requestSenderService,
+		requestSender:       requestSender,
 		databaseInfoService: databaseInfoService,
 	}
 }
diff --git a/internal/usecases/consume/consume_test.go b/internal/usecases/consume/consume_test.go
index ecdf68c..559e24a 100644
--- a/internal/usecases/consume/consume_test.go
+++ b/internal/usecases/consume/consume_test.go
@@ -6,7 +6,6 @@ import (
 	"query-service/internal/entity"
 	"query-service/internal/usecases/databaseinfo/mockdatabaseinfo"
 	"query-service/internal/usecases/produce"
-	"query-service/internal/usecases/request/mockrequest"
 
 	"testing"
 
@@ -14,17 +13,18 @@ import (
 	"git.science.uu.nl/datastrophe/keyvaluestore"
 	"git.science.uu.nl/datastrophe/query-conversion"
 	"git.science.uu.nl/datastrophe/query-conversion/aql"
+	queryexecution "git.science.uu.nl/datastrophe/query-execution"
 	"github.com/stretchr/testify/assert"
 )
 
 type testSuite struct {
-	mockBroker           *broker.MockDriver
-	mockKeyValueStore    keyvaluestore.Interface
-	produceService       *produce.Service
-	queryConverter       query.Converter
-	requestSenderService *mockrequest.Service
-	databaseInfoService  *mockdatabaseinfo.Service
-	service              *Service
+	mockBroker          *broker.MockDriver
+	mockKeyValueStore   keyvaluestore.Interface
+	produceService      *produce.Service
+	queryConverter      query.Converter
+	requestSender       *queryexecution.MockService
+	databaseInfoService *mockdatabaseinfo.Service
+	service             *Service
 }
 
 var ts *testSuite
@@ -39,14 +39,14 @@ func createTestSuite() {
 	mockBroker := broker.NewMockDriver().(*broker.MockDriver)
 	mockKeyValueStore := keyvaluestore.NewMockDriver()
 	ts = &testSuite{
-		mockBroker:           mockBroker,
-		mockKeyValueStore:    mockKeyValueStore,
-		produceService:       produce.NewService(mockBroker, mockKeyValueStore),
-		queryConverter:       aql.NewService(),
-		requestSenderService: mockrequest.NewService(),
-		databaseInfoService:  mockdatabaseinfo.NewService(),
+		mockBroker:          mockBroker,
+		mockKeyValueStore:   mockKeyValueStore,
+		produceService:      produce.NewService(mockBroker, mockKeyValueStore),
+		queryConverter:      aql.NewService(),
+		requestSender:       queryexecution.NewMockService(),
+		databaseInfoService: mockdatabaseinfo.NewService(),
 	}
-	ts.service = NewService(mockBroker, ts.produceService, ts.queryConverter, ts.requestSenderService, ts.databaseInfoService)
+	ts.service = NewService(mockBroker, ts.produceService, ts.queryConverter, ts.requestSender, ts.databaseInfoService)
 
 	// Set routing in the mock keyvaluestore
 	ts.mockKeyValueStore.Set(context.Background(), "mock-session", "mock-queue")
@@ -188,7 +188,7 @@ func TestDatabaseErrorHandled(t *testing.T) {
 	}
 
 	// Make it so that the request sender service throws an error
-	ts.requestSenderService.ToggleError()
+	ts.requestSender.ToggleError()
 
 	// Assert that there have not been any messages sent yet
 	assert.Empty(t, ts.mockBroker.Messages)
@@ -202,7 +202,7 @@ func TestDatabaseErrorHandled(t *testing.T) {
 	assert.Equal(t, "query_database_error", errorMsg.Type)
 
 	// Turn of error throwing in request service
-	ts.requestSenderService.ToggleError()
+	ts.requestSender.ToggleError()
 }
 
 func TestQueryConversionErrorHandled(t *testing.T) {
diff --git a/internal/usecases/consume/handlemessage.go b/internal/usecases/consume/handlemessage.go
index 7efd3af..da2e1fb 100644
--- a/internal/usecases/consume/handlemessage.go
+++ b/internal/usecases/consume/handlemessage.go
@@ -89,7 +89,7 @@ func (s *Service) HandleMessage(msg *broker.Message) {
 
 	// execute and retrieve result
 	// convert result to general (node-link) format
-	result, err := s.requestSender.SendAQLQuery(*query, databaseInfo.Username, databaseInfo.Password, databaseInfo.URL, databaseInfo.Port, databaseInfo.InternalDatabaseName)
+	result, err := s.requestSender.ExecuteQuery(*query, databaseInfo.Username, databaseInfo.Password, databaseInfo.URL, databaseInfo.Port, databaseInfo.InternalDatabaseName)
 	if err != nil {
 		errorMsg := entity.MessageStruct{
 			Type:  "query_database_error",
diff --git a/internal/usecases/request/interface.go b/internal/usecases/request/interface.go
deleted file mode 100644
index e5c1f63..0000000
--- a/internal/usecases/request/interface.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package request
-
-// UseCase is an interface describing the request usecases
-type UseCase interface {
-	SendAQLQuery(query string, username string, password string, hostname string, port int, database string) (*[]byte, error)
-}
diff --git a/internal/usecases/request/mockrequest/mockrequest.go b/internal/usecases/request/mockrequest/mockrequest.go
deleted file mode 100644
index 7b52e42..0000000
--- a/internal/usecases/request/mockrequest/mockrequest.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package mockrequest
-
-import (
-	"encoding/json"
-	"errors"
-)
-
-// A Service implements the request usecases (mock)
-type Service struct {
-	throwError bool
-}
-
-// NewService creates a new service (mock)
-func NewService() *Service {
-	return &Service{
-		throwError: false,
-	}
-}
-
-// SendAQLQuery sends the query to arangoDB and parses the result (mock)
-func (s *Service) SendAQLQuery(query string, username string, password string, hostname string, port int, database string) (*[]byte, error) {
-	mockResult, _ := json.Marshal("test")
-
-	if !s.throwError {
-		return &mockResult, nil
-	}
-	return nil, errors.New("Database error")
-}
-
-// ToggleError decides whether the convert function throws an error
-func (s *Service) ToggleError() {
-	s.throwError = !s.throwError
-}
diff --git a/internal/usecases/request/request.go b/internal/usecases/request/request.go
deleted file mode 100644
index ce3b7d2..0000000
--- a/internal/usecases/request/request.go
+++ /dev/null
@@ -1,174 +0,0 @@
-package request
-
-import (
-	"context"
-	"crypto/tls"
-	"fmt"
-	"log"
-	"query-service/internal/entity"
-
-	"encoding/json"
-	"io/ioutil"
-
-	driver "github.com/arangodb/go-driver"
-	"github.com/arangodb/go-driver/http"
-)
-
-/*
-SendAQLQuery send AQL string query to database and returns a JSON object in a general format
-
-Parameters: AQLQuery is a string containing the query that will be send to the database
-
-Return: a map with two entries: "nodes" with a list of vertices/nodes and "edges" with a list of edges
-that will be returned to the frontend
-*/
-func (s *Service) SendAQLQuery(query string, username string, password string, hostname string, port int, database string) (*[]byte, error) {
-	var queryResult = make(map[string][]entity.Document)
-	conn, err := http.NewConnection(http.ConnectionConfig{
-		Endpoints: []string{fmt.Sprintf("%s:%d", hostname, port)},
-		TLSConfig: &tls.Config{InsecureSkipVerify: true},
-	})
-	if err != nil {
-		log.Println("could not connect to database") // Handle error
-		return nil, err
-	}
-	c, err := driver.NewClient(driver.ClientConfig{
-		Connection:     conn,
-		Authentication: driver.BasicAuthentication(username, password),
-	})
-	if err != nil {
-		log.Println("Could not log in to the ArangoDB") // Handle error
-		return nil, err
-	}
-
-	ctx := context.Background()
-	db, err := c.Database(ctx, database)
-	if err != nil {
-		// handle error
-		log.Println(err)
-		return nil, err
-	}
-
-	cursor, err := db.Query(ctx, query, nil)
-	if err != nil {
-		log.Println("Invalid query") // handle error
-		return nil, err
-	}
-	defer cursor.Close()
-
-	//Loop through the resulting documents
-	listContainer := entity.ListContainer{}
-	num := -1.0
-	isNum := false
-
-	for {
-		var doc interface{}
-		_, err := cursor.ReadDocument(ctx, &doc)
-		if driver.IsNoMoreDocuments(err) {
-			break
-		} else if err != nil {
-			// handle other errors
-			fmt.Println(err)
-			return nil, err
-		}
-
-		// Switch on the type of return, to filter out the case of a single number
-		switch doc.(type) {
-		case float64:
-			num = doc.(float64)
-			isNum = true
-			break
-		case map[string]interface{}:
-			pdoc := doc.(map[string]interface{})
-			parseResult(pdoc, &listContainer)
-			break
-		default:
-			fmt.Println("Incompatible result type")
-			break
-		}
-	}
-
-	if !isNum {
-		// Return nodes and edges
-		queryResult["nodes"] = listContainer.NodeList
-		queryResult["edges"] = listContainer.EdgeList
-
-		jsonQ, err := json.Marshal(queryResult)
-		return &jsonQ, err
-	}
-	// Return just a number
-	numQ, err := json.Marshal(num)
-	return &numQ, err
-
-}
-
-/* parseResult takes the result of the query and translates this to two lists: a nodelist and an edgelist, stored in a listcontainer
-
-Parameters: doc is the document with the nodes and vertices that came back from the database,
-listContainer is a struct containing the nodelist and edgelist that will be returned to the frontend
-
-Return: Nothing because the result is stored in the listContainer
-*/
-func parseResult(doc map[string]interface{}, listContainer *entity.ListContainer) {
-	vertices := doc["vertices"].([]interface{})
-	edges := doc["edges"].([]interface{})
-
-	for _, vertex := range vertices {
-		vertexDoc := vertex.(map[string]interface{})
-
-		(*listContainer).NodeList = append((*listContainer).NodeList, parseNode(vertexDoc))
-	}
-
-	for _, edge := range edges {
-		edgeDoc := edge.(map[string]interface{})
-
-		(*listContainer).EdgeList = append((*listContainer).EdgeList, parseEdge(edgeDoc))
-	}
-}
-
-/* parseEdge parses the data of an edge to an output-friendly format
-Parameters: d is a single entry of an edge
-
-Return: a document with almost the same structure as before, but the attributes are grouped
-*/
-func parseEdge(doc map[string]interface{}) entity.Document {
-	data := make(entity.Document)
-	data["_id"] = doc["_id"]
-	delete(doc, "_id")
-	data["_key"] = doc["_key"]
-	delete(doc, "_key")
-	data["_rev"] = doc["_rev"]
-	delete(doc, "_rev")
-	data["_from"] = doc["_from"]
-	delete(doc, "_from")
-	data["_to"] = doc["_to"]
-	delete(doc, "_to")
-	data["attributes"] = doc
-
-	return data
-}
-
-// writeJSON writes a json file for testing purposes
-func writeJSON(queryResult map[string][]entity.Document) {
-	file, _ := json.MarshalIndent(queryResult, "", " ")
-
-	_ = ioutil.WriteFile("result.json", file, 0644)
-}
-
-/* parseEdge parses the data of a node to an output-friendly format
-Parameters: d is a single entry of an node
-
-Return: a document with almost the same structure as before, but the attributes are grouped
-*/
-func parseNode(doc map[string]interface{}) entity.Document {
-	data := make(entity.Document)
-	data["_id"] = doc["_id"]
-	delete(doc, "_id")
-	data["_key"] = doc["_key"]
-	delete(doc, "_key")
-	data["_rev"] = doc["_rev"]
-	delete(doc, "_rev")
-	data["attributes"] = doc
-
-	return data
-}
diff --git a/internal/usecases/request/requestStructs.go b/internal/usecases/request/requestStructs.go
deleted file mode 100644
index b2a001f..0000000
--- a/internal/usecases/request/requestStructs.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package request
-
-// Service is a struct used to store this use case in
-type Service struct {
-}
-
-// NewService creates a new instantion of this use case
-func NewService() *Service {
-	return &Service{}
-}
-- 
GitLab