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