Merged in feature/testquery (pull request #39)

Test Query

* depstextandclean

* startedcleaningresult

* resulttidyup

* roundone

* cleaning

* unsyncedquery

* startedtestsandsimplification

* api

* querytests

* resultprocessortests

* unittests

* cleanup
This commit is contained in:
Michael McGuinness
2025-01-29 11:52:37 +00:00
parent c36b0cdcf8
commit 0ac5ff9e15
109 changed files with 2804 additions and 2100 deletions
+9 -9
View File
@@ -5,7 +5,7 @@ import (
"fmt"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
contextfull "queryorchestration/internal/query/types/contextFull"
jsonextractor "queryorchestration/internal/query/types/jsonExtractor"
@@ -13,7 +13,7 @@ import (
"github.com/jackc/pgx/v5/pgtype"
)
func (s *Service) Create(ctx context.Context, entity *queryprocessor.Create) (uuid.UUID, error) {
func (s *Service) Create(ctx context.Context, entity *resultprocessor.Create) (uuid.UUID, error) {
err := s.normalizeCreate(ctx, entity)
if err != nil {
return uuid.Nil, err
@@ -27,7 +27,7 @@ func (s *Service) Create(ctx context.Context, entity *queryprocessor.Create) (uu
return id, err
}
func (s *Service) normalizeCreate(ctx context.Context, entity *queryprocessor.Create) error {
func (s *Service) normalizeCreate(ctx context.Context, entity *resultprocessor.Create) error {
err := s.NormalizeQueryIDs(ctx, entity)
if err != nil {
return err
@@ -51,7 +51,7 @@ func (s *Service) normalizeCreate(ctx context.Context, entity *queryprocessor.Cr
return nil
}
func (s *Service) submitCreate(ctx context.Context, entity *queryprocessor.Create) (uuid.UUID, error) {
func (s *Service) submitCreate(ctx context.Context, entity *resultprocessor.Create) (uuid.UUID, error) {
query, err := parseCreateQuery(entity)
if err != nil {
return uuid.Nil, err
@@ -103,11 +103,11 @@ func (s *Service) submitCreate(ctx context.Context, entity *queryprocessor.Creat
}
func (s *Service) getCreator(qType queryprocessor.Type) (queryprocessor.Creator, error) {
func (s *Service) getCreator(qType resultprocessor.Type) (resultprocessor.Creator, error) {
switch qType {
case queryprocessor.TypeJsonExtractor:
case resultprocessor.TypeJsonExtractor:
return jsonextractor.NewCreator(s.db), nil
case queryprocessor.TypeContextFull:
case resultprocessor.TypeContextFull:
return contextfull.NewCreator(s.db), nil
default:
return nil, fmt.Errorf("attempting to process invalid query type")
@@ -120,8 +120,8 @@ type createQuery struct {
Config *[]byte
}
func parseCreateQuery(q *queryprocessor.Create) (*createQuery, error) {
t, err := queryprocessor.ToDBQueryType(q.Type)
func parseCreateQuery(q *resultprocessor.Create) (*createQuery, error) {
t, err := resultprocessor.ToDBQueryType(q.Type)
if err != nil {
return nil, err
}
+13 -17
View File
@@ -6,7 +6,7 @@ import (
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/query"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
"testing"
"github.com/google/uuid"
@@ -27,24 +27,24 @@ func TestCreate(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := query.New(db)
svc := query.New(db, &query.Services{})
config := "{\"path\":\"example_path\"}"
q := query.Query{
ID: uuid.New(),
Type: queryprocessor.TypeJsonExtractor,
Type: resultprocessor.TypeJsonExtractor,
RequiredQueryIDs: &[]uuid.UUID{
uuid.New(),
},
Config: &config,
}
create := &queryprocessor.Create{
create := &resultprocessor.Create{
Type: q.Type,
RequiredQueryIDs: q.RequiredQueryIDs,
Config: q.Config,
}
dbType, err := queryprocessor.ToDBQueryType(create.Type)
dbType, err := resultprocessor.ToDBQueryType(create.Type)
assert.Nil(t, err)
pool.ExpectQuery("name: AllQueriesExist :one").WithArgs(database.MustToDBUUIDArray(*create.RequiredQueryIDs)).WillReturnRows(
@@ -81,17 +81,17 @@ func TestCreateMinimal(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := query.New(db)
svc := query.New(db, &query.Services{})
q := query.Query{
ID: uuid.New(),
Type: queryprocessor.TypeJsonExtractor,
Type: resultprocessor.TypeJsonExtractor,
}
create := &queryprocessor.Create{
create := &resultprocessor.Create{
Type: q.Type,
}
dbType, err := queryprocessor.ToDBQueryType(create.Type)
dbType, err := resultprocessor.ToDBQueryType(create.Type)
assert.Nil(t, err)
pool.ExpectBeginTx(pgx.TxOptions{})
@@ -118,17 +118,13 @@ func TestCreateRollback(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := query.New(db)
svc := query.New(db, &query.Services{})
q := query.Query{
ID: uuid.New(),
Type: queryprocessor.TypeJsonExtractor,
}
create := &queryprocessor.Create{
Type: q.Type,
create := &resultprocessor.Create{
Type: resultprocessor.TypeJsonExtractor,
}
dbType, err := queryprocessor.ToDBQueryType(create.Type)
dbType, err := resultprocessor.ToDBQueryType(create.Type)
assert.Nil(t, err)
pool.ExpectBeginTx(pgx.TxOptions{})
+22 -22
View File
@@ -4,7 +4,7 @@ import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
"testing"
"github.com/google/uuid"
@@ -23,27 +23,27 @@ func TestGetCreator(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := New(db)
svc := New(db, &Services{})
queryType := queryprocessor.Type(queryprocessor.TypeContextFull)
queryType := resultprocessor.Type(resultprocessor.TypeContextFull)
creator, err := svc.getCreator(queryType)
assert.Nil(t, err)
assert.NotNil(t, creator)
queryType = queryprocessor.Type(queryprocessor.TypeJsonExtractor)
queryType = resultprocessor.Type(resultprocessor.TypeJsonExtractor)
creator, err = svc.getCreator(queryType)
assert.Nil(t, err)
assert.NotNil(t, creator)
queryType = queryprocessor.Type(-1)
queryType = resultprocessor.Type(-1)
_, err = svc.getCreator(queryType)
assert.NotNil(t, err)
}
func TestParseCreateQuery(t *testing.T) {
cfg := "{\"key\":\"value\"}"
cQuery := &queryprocessor.Create{
Type: queryprocessor.TypeContextFull,
cQuery := &resultprocessor.Create{
Type: resultprocessor.TypeContextFull,
RequiredQueryIDs: &[]uuid.UUID{
uuid.New(),
},
@@ -63,8 +63,8 @@ func TestParseCreateQuery(t *testing.T) {
func TestParseCreateQueryInvalidType(t *testing.T) {
cfg := "{\"key\":\"value\"}"
cQuery := &queryprocessor.Create{
Type: queryprocessor.Type(-1),
cQuery := &resultprocessor.Create{
Type: resultprocessor.Type(-1),
RequiredQueryIDs: &[]uuid.UUID{
uuid.New(),
},
@@ -87,24 +87,24 @@ func TestSubmitCreate(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := New(db)
svc := New(db, &Services{})
config := "{\"path\":\"example_path\"}"
q := Query{
ID: uuid.New(),
Type: queryprocessor.TypeJsonExtractor,
Type: resultprocessor.TypeJsonExtractor,
RequiredQueryIDs: &[]uuid.UUID{
uuid.New(),
},
Config: &config,
}
create := &queryprocessor.Create{
create := &resultprocessor.Create{
Type: q.Type,
RequiredQueryIDs: q.RequiredQueryIDs,
Config: q.Config,
}
dbType, err := queryprocessor.ToDBQueryType(create.Type)
dbType, err := resultprocessor.ToDBQueryType(create.Type)
assert.Nil(t, err)
pool.ExpectBeginTx(pgx.TxOptions{})
@@ -137,17 +137,17 @@ func TestSubmitCreateNoReqsOrConfig(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := New(db)
svc := New(db, &Services{})
q := Query{
ID: uuid.New(),
Type: queryprocessor.TypeJsonExtractor,
Type: resultprocessor.TypeJsonExtractor,
}
create := &queryprocessor.Create{
create := &resultprocessor.Create{
Type: q.Type,
}
dbType, err := queryprocessor.ToDBQueryType(create.Type)
dbType, err := resultprocessor.ToDBQueryType(create.Type)
assert.Nil(t, err)
pool.ExpectBeginTx(pgx.TxOptions{})
@@ -174,10 +174,10 @@ func TestNormalizeCreate(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := New(db)
svc := New(db, &Services{})
create := &queryprocessor.Create{
Type: queryprocessor.TypeJsonExtractor,
create := &resultprocessor.Create{
Type: resultprocessor.TypeJsonExtractor,
RequiredQueryIDs: &[]uuid.UUID{},
}
@@ -190,8 +190,8 @@ func TestNormalizeCreate(t *testing.T) {
err = svc.normalizeCreate(ctx, create)
assert.Nil(t, err)
assert.EqualExportedValues(t, queryprocessor.Create{
Type: queryprocessor.TypeJsonExtractor,
assert.EqualExportedValues(t, resultprocessor.Create{
Type: resultprocessor.TypeJsonExtractor,
Config: nil,
RequiredQueryIDs: nil,
}, *create)
+14 -47
View File
@@ -4,20 +4,32 @@ import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
"github.com/google/uuid"
)
type Query struct {
ID uuid.UUID
Type queryprocessor.Type
Type resultprocessor.Type
ActiveVersion int32
LatestVersion int32
RequiredQueryIDs *[]uuid.UUID
Config *string
}
func (s *Service) GetWithVersion(ctx context.Context, id uuid.UUID, version int32) (*Query, error) {
query, err := s.db.Queries.GetQueryWithVersion(ctx, &repository.GetQueryWithVersionParams{
ID: database.MustToDBUUID(id),
Addedversion: version,
})
if err != nil {
return nil, err
}
return ParseQueryWithVersion(query)
}
func (s *Service) Get(ctx context.Context, id uuid.UUID) (*Query, error) {
query, err := s.db.Queries.GetQuery(ctx, database.MustToDBUUID(id))
if err != nil {
@@ -26,48 +38,3 @@ func (s *Service) Get(ctx context.Context, id uuid.UUID) (*Query, error) {
return ParseFullActiveQuery(query)
}
func ParseFullActiveQuery(q *repository.Fullactivequery) (*Query, error) {
var reqQueryIDs *[]uuid.UUID
if len(q.Requiredids) > 0 {
rQ, err := database.ToUUIDArray(q.Requiredids)
if err != nil {
return nil, err
}
reqQueryIDs = &rQ
}
qType, err := queryprocessor.ParseDBType(q.Type)
if err != nil {
return nil, err
}
var scfg *string
if q.Config != nil && string(q.Config) != "" {
s := string(q.Config)
scfg = &s
}
return &Query{
ID: database.MustToUUID(q.ID),
ActiveVersion: q.Activeversion,
LatestVersion: q.Latestversion,
Type: qType,
RequiredQueryIDs: reqQueryIDs,
Config: scfg,
}, nil
}
func ParseFullActiveQueryArray(q []*repository.Fullactivequery) ([]*Query, error) {
queries := make([]*Query, len(q))
for index, query := range q {
q, err := ParseFullActiveQuery(query)
if err != nil {
return nil, err
}
queries[index] = q
}
return queries, nil
}
+35 -52
View File
@@ -5,7 +5,7 @@ import (
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/query"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
"testing"
"github.com/google/uuid"
@@ -25,12 +25,12 @@ func TestGet(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := query.New(db)
svc := query.New(db, &query.Services{})
config := "{\"path\":\"example_path\"}"
query := query.Query{
ID: uuid.New(),
Type: queryprocessor.TypeJsonExtractor,
Type: resultprocessor.TypeJsonExtractor,
ActiveVersion: int32(1),
LatestVersion: int32(1),
RequiredQueryIDs: &[]uuid.UUID{
@@ -52,60 +52,43 @@ func TestGet(t *testing.T) {
assert.EqualExportedValues(t, query, *returnQuery)
}
func TestFullActiveQueryEmpty(t *testing.T) {
dbQuery := &repository.Fullactivequery{
ID: database.MustToDBUUID(uuid.New()),
Type: repository.QuerytypeContextFull,
Activeversion: int32(1),
Latestversion: int32(2),
}
func TestGetWithVersion(t *testing.T) {
ctx := context.Background()
out, err := query.ParseFullActiveQuery(dbQuery)
assert.Nil(t, err)
assert.EqualExportedValues(t, query.Query{
ID: database.MustToUUID(dbQuery.ID),
Type: queryprocessor.TypeContextFull,
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
svc := query.New(db, &query.Services{})
config := "{\"path\":\"example_path\"}"
query := query.Query{
ID: uuid.New(),
Type: resultprocessor.TypeJsonExtractor,
ActiveVersion: int32(1),
LatestVersion: int32(2),
}, *out)
}
func TestFullActiveQueryWithNullUUID(t *testing.T) {
dbQuery := &repository.Fullactivequery{
ID: database.MustToDBUUID(uuid.New()),
Type: repository.QuerytypeContextFull,
Activeversion: int32(1),
Latestversion: int32(2),
LatestVersion: int32(3),
RequiredQueryIDs: &[]uuid.UUID{
uuid.New(),
},
Config: &config,
}
out, err := query.ParseFullActiveQuery(dbQuery)
assert.Nil(t, err)
assert.EqualExportedValues(t, query.Query{
ID: database.MustToUUID(dbQuery.ID),
Type: queryprocessor.TypeContextFull,
ActiveVersion: int32(1),
LatestVersion: int32(2),
}, *out)
}
version := int32(2)
func TestFullActiveQueryArray(t *testing.T) {
dbQueries := []*repository.Fullactivequery{
{
ID: database.MustToDBUUID(uuid.New()),
Type: repository.QuerytypeContextFull,
Activeversion: int32(1),
Latestversion: int32(2),
},
}
dbReqIDs := database.MustToDBUUIDArray(*query.RequiredQueryIDs)
out, err := query.ParseFullActiveQueryArray(dbQueries)
pool.ExpectQuery("name: GetQueryWithVersion :one").WithArgs(database.MustToDBUUID(query.ID), version).WillReturnRows(
pgxmock.NewRows([]string{"id", "type", "activeVersion", "latestVersion", "config", "requiredIds"}).
AddRow(database.MustToDBUUID(query.ID), repository.QuerytypeJsonExtractor, query.ActiveVersion, query.LatestVersion, []byte(config), dbReqIDs),
)
returnQuery, err := svc.GetWithVersion(ctx, query.ID, version)
assert.Nil(t, err)
assert.EqualExportedValues(t, []*query.Query{
{
ID: database.MustToUUID(dbQueries[0].ID),
Type: queryprocessor.TypeContextFull,
ActiveVersion: int32(1),
LatestVersion: int32(2),
},
}, out)
assert.EqualExportedValues(t, query, *returnQuery)
}
+18 -4
View File
@@ -2,12 +2,12 @@ package query
import (
"context"
"queryorchestration/internal/database"
"github.com/google/uuid"
)
type ListFilters struct {
}
func (s *Service) List(ctx context.Context, filters ListFilters) ([]*Query, error) {
func (s *Service) List(ctx context.Context) ([]*Query, error) {
dbQueries, err := s.db.Queries.ListQueries(ctx)
if err != nil {
return nil, err
@@ -20,3 +20,17 @@ func (s *Service) List(ctx context.Context, filters ListFilters) ([]*Query, erro
return queries, nil
}
func (s *Service) ListById(ctx context.Context, ids []uuid.UUID) ([]*Query, error) {
dbQueries, err := s.db.Queries.ListQueriesById(ctx, database.MustToDBUUIDArray(ids))
if err != nil {
return nil, err
}
queries, err := ParseFullActiveQueryArray(dbQueries)
if err != nil {
return nil, err
}
return queries, nil
}
+10 -13
View File
@@ -5,10 +5,11 @@ import (
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/query"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/pashagolub/pgxmock/v3"
"github.com/stretchr/testify/assert"
)
@@ -25,12 +26,12 @@ func TestList(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := query.New(db)
svc := query.New(db, &query.Services{})
config := "{\"path\":\"example_path\"}"
q := &query.Query{
ID: uuid.New(),
Type: queryprocessor.TypeJsonExtractor,
Type: resultprocessor.TypeJsonExtractor,
ActiveVersion: int32(1),
LatestVersion: int32(1),
RequiredQueryIDs: &[]uuid.UUID{
@@ -41,20 +42,18 @@ func TestList(t *testing.T) {
dbReqIDs := database.MustToDBUUIDArray(*q.RequiredQueryIDs)
filters := query.ListFilters{}
pool.ExpectQuery("name: ListQueries :many").WithArgs().WillReturnRows(
pgxmock.NewRows([]string{"id", "type", "activeVersion", "latestVersion", "config", "requiredIds"}).
AddRow(database.MustToDBUUID(q.ID), repository.QuerytypeJsonExtractor, q.ActiveVersion, q.LatestVersion, []byte(config), dbReqIDs),
)
resList, err := svc.List(ctx, filters)
resList, err := svc.List(ctx)
assert.Nil(t, err)
assert.EqualExportedValues(t, []*query.Query{q}, resList)
}
func TestListFilterType(t *testing.T) {
func TestListById(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
@@ -66,12 +65,12 @@ func TestListFilterType(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := query.New(db)
svc := query.New(db, &query.Services{})
config := "{\"path\":\"example_path\"}"
q := &query.Query{
ID: uuid.New(),
Type: queryprocessor.TypeJsonExtractor,
Type: resultprocessor.TypeJsonExtractor,
ActiveVersion: int32(1),
LatestVersion: int32(1),
RequiredQueryIDs: &[]uuid.UUID{
@@ -82,14 +81,12 @@ func TestListFilterType(t *testing.T) {
dbReqIDs := database.MustToDBUUIDArray(*q.RequiredQueryIDs)
filters := query.ListFilters{}
pool.ExpectQuery("name: ListQueries :many").WithArgs().WillReturnRows(
pool.ExpectQuery("name: ListQueriesById :many").WithArgs([]pgtype.UUID{database.MustToDBUUID(q.ID)}).WillReturnRows(
pgxmock.NewRows([]string{"id", "type", "activeVersion", "latestVersion", "config", "requiredIds"}).
AddRow(database.MustToDBUUID(q.ID), repository.QuerytypeJsonExtractor, q.ActiveVersion, q.LatestVersion, []byte(config), dbReqIDs),
)
resList, err := svc.List(ctx, filters)
resList, err := svc.ListById(ctx, []uuid.UUID{q.ID})
assert.Nil(t, err)
assert.EqualExportedValues(t, []*query.Query{q}, resList)
+2 -2
View File
@@ -6,7 +6,7 @@ import (
"errors"
"fmt"
"queryorchestration/internal/database"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
"queryorchestration/internal/server/validation"
"strings"
@@ -83,7 +83,7 @@ func (s *Service) NormalizeQueryIDs(ctx context.Context, ids RequiredQueryIDs) e
return nil
}
func (s *Service) normalizeActiveVersion(current *Query, entity *queryprocessor.Update) error {
func (s *Service) normalizeActiveVersion(current *Query, entity *resultprocessor.Update) error {
if current == nil {
return errors.New("current query required")
}
+4 -4
View File
@@ -5,7 +5,7 @@ import (
"errors"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
"testing"
"github.com/google/uuid"
@@ -19,7 +19,7 @@ func TestNormalizeConfig(t *testing.T) {
err := s.normalizeConfig(nil)
assert.Nil(t, err)
entity := queryprocessor.Create{}
entity := resultprocessor.Create{}
entity.Config = nil
err = s.normalizeConfig(&entity)
@@ -84,7 +84,7 @@ func TestNormalizeQueryIDs(t *testing.T) {
err = s.NormalizeQueryIDs(ctx, nil)
assert.Nil(t, err)
entity := queryprocessor.Create{}
entity := resultprocessor.Create{}
entity.RequiredQueryIDs = nil
err = s.NormalizeQueryIDs(ctx, &entity)
@@ -150,7 +150,7 @@ func TestNormalizeActiveVersion(t *testing.T) {
ActiveVersion: 2,
LatestVersion: 4,
}
entity := queryprocessor.Update{}
entity := resultprocessor.Update{}
err = s.normalizeActiveVersion(nil, &entity)
assert.Error(t, err)
+65
View File
@@ -0,0 +1,65 @@
package query
import (
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
resultprocessor "queryorchestration/internal/query/result/processor"
"github.com/google/uuid"
)
func ParseQueryWithVersion(q *repository.GetQueryWithVersionRow) (*Query, error) {
return ParseFullActiveQuery(&repository.Fullactivequery{
ID: q.ID,
Type: q.Type,
Activeversion: q.Activeversion,
Latestversion: q.Latestversion,
Config: q.Config,
Requiredids: q.Requiredids,
})
}
func ParseFullActiveQuery(q *repository.Fullactivequery) (*Query, error) {
var reqQueryIDs *[]uuid.UUID
if len(q.Requiredids) > 0 {
rQ, err := database.ToUUIDArray(q.Requiredids)
if err != nil {
return nil, err
}
reqQueryIDs = &rQ
}
qType, err := resultprocessor.ParseDBType(q.Type)
if err != nil {
return nil, err
}
var scfg *string
if q.Config != nil && string(q.Config) != "" {
s := string(q.Config)
scfg = &s
}
return &Query{
ID: database.MustToUUID(q.ID),
ActiveVersion: q.Activeversion,
LatestVersion: q.Latestversion,
Type: qType,
RequiredQueryIDs: reqQueryIDs,
Config: scfg,
}, nil
}
func ParseFullActiveQueryArray(q []*repository.Fullactivequery) ([]*Query, error) {
queries := make([]*Query, len(q))
for index, query := range q {
q, err := ParseFullActiveQuery(query)
if err != nil {
return nil, err
}
queries[index] = q
}
return queries, nil
}
+62 -4
View File
@@ -4,7 +4,7 @@ import (
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/query"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
"testing"
"github.com/google/uuid"
@@ -16,7 +16,7 @@ func TestParseQuery(t *testing.T) {
cfg := "example"
q := &query.Query{
ID: uuid.New(),
Type: queryprocessor.TypeJsonExtractor,
Type: resultprocessor.TypeJsonExtractor,
ActiveVersion: int32(1),
LatestVersion: int32(2),
RequiredQueryIDs: &[]uuid.UUID{
@@ -26,7 +26,7 @@ func TestParseQuery(t *testing.T) {
}
out := query.ParseQuery(q)
assert.EqualExportedValues(t, queryprocessor.Query{
assert.EqualExportedValues(t, resultprocessor.Query{
ID: q.ID,
Type: q.Type,
Version: q.ActiveVersion,
@@ -52,7 +52,7 @@ func TestParseFullActiveQuery(t *testing.T) {
bcfg := string(q.Config)
assert.EqualExportedValues(t, query.Query{
ID: database.MustToUUID(q.ID),
Type: queryprocessor.TypeContextFull,
Type: resultprocessor.TypeContextFull,
ActiveVersion: q.Activeversion,
LatestVersion: q.Latestversion,
RequiredQueryIDs: &[]uuid.UUID{
@@ -61,3 +61,61 @@ func TestParseFullActiveQuery(t *testing.T) {
Config: &bcfg,
}, *out)
}
func TestFullActiveQueryEmpty(t *testing.T) {
dbQuery := &repository.Fullactivequery{
ID: database.MustToDBUUID(uuid.New()),
Type: repository.QuerytypeContextFull,
Activeversion: int32(1),
Latestversion: int32(2),
}
out, err := query.ParseFullActiveQuery(dbQuery)
assert.Nil(t, err)
assert.EqualExportedValues(t, query.Query{
ID: database.MustToUUID(dbQuery.ID),
Type: resultprocessor.TypeContextFull,
ActiveVersion: int32(1),
LatestVersion: int32(2),
}, *out)
}
func TestFullActiveQueryWithNullUUID(t *testing.T) {
dbQuery := &repository.Fullactivequery{
ID: database.MustToDBUUID(uuid.New()),
Type: repository.QuerytypeContextFull,
Activeversion: int32(1),
Latestversion: int32(2),
}
out, err := query.ParseFullActiveQuery(dbQuery)
assert.Nil(t, err)
assert.EqualExportedValues(t, query.Query{
ID: database.MustToUUID(dbQuery.ID),
Type: resultprocessor.TypeContextFull,
ActiveVersion: int32(1),
LatestVersion: int32(2),
}, *out)
}
func TestFullActiveQueryArray(t *testing.T) {
dbQueries := []*repository.Fullactivequery{
{
ID: database.MustToDBUUID(uuid.New()),
Type: repository.QuerytypeContextFull,
Activeversion: int32(1),
Latestversion: int32(2),
},
}
out, err := query.ParseFullActiveQueryArray(dbQueries)
assert.Nil(t, err)
assert.EqualExportedValues(t, []*query.Query{
{
ID: database.MustToUUID(dbQueries[0].ID),
Type: resultprocessor.TypeContextFull,
ActiveVersion: int32(1),
LatestVersion: int32(2),
},
}, out)
}
-109
View File
@@ -1,109 +0,0 @@
package queryprocessor_test
import (
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/stretchr/testify/assert"
)
func TestParseDBCollectorQuery(t *testing.T) {
dbResult := repository.Collectorquerydependencytree{
Collectorid: pgtype.UUID{},
Queryid: pgtype.UUID{},
Requiredids: []pgtype.UUID{},
Type: repository.QuerytypeJsonExtractor,
Queryversion: 1,
}
value, err := queryprocessor.ParseDBCollectorQuery(&dbResult)
assert.Nil(t, err)
assert.Equal(t, uuid.Nil, value.ID)
assert.Nil(t, value.RequiredQueryIDs)
assert.Equal(t, int32(1), value.Version)
assert.Equal(t, queryprocessor.Type(queryprocessor.TypeJsonExtractor), value.Type)
dbResult.Type = repository.Querytype("")
_, err = queryprocessor.ParseDBCollectorQuery(&dbResult)
assert.EqualError(t, err, "invalid database query type")
}
func TestParseDBNullType(t *testing.T) {
qType := repository.NullQuerytype{Valid: true, Querytype: repository.QuerytypeJsonExtractor}
value, err := queryprocessor.ParseDBNullType(qType)
assert.Nil(t, err)
assert.Equal(t, queryprocessor.Type(queryprocessor.TypeJsonExtractor), value)
qType = repository.NullQuerytype{}
_, err = queryprocessor.ParseDBNullType(qType)
assert.EqualError(t, err, "invalid database query type")
qType = repository.NullQuerytype{Valid: true}
_, err = queryprocessor.ParseDBNullType(qType)
assert.EqualError(t, err, "invalid database query type")
}
func TestParseDBType(t *testing.T) {
qType := repository.QuerytypeJsonExtractor
value, err := queryprocessor.ParseDBType(qType)
assert.Nil(t, err)
assert.Equal(t, queryprocessor.Type(queryprocessor.TypeJsonExtractor), value)
qType = repository.QuerytypeContextFull
value, err = queryprocessor.ParseDBType(qType)
assert.Nil(t, err)
assert.Equal(t, queryprocessor.Type(queryprocessor.TypeContextFull), value)
}
func TestToDBQueryType(t *testing.T) {
dbQueryType := queryprocessor.Type(queryprocessor.TypeJsonExtractor)
value, err := queryprocessor.ToDBQueryType(dbQueryType)
assert.Nil(t, err)
assert.Equal(t, repository.Querytype(repository.QuerytypeJsonExtractor), value)
dbQueryType = queryprocessor.Type(-1)
_, err = queryprocessor.ToDBQueryType(dbQueryType)
assert.EqualError(t, err, "invalid database query type")
dbQueryType = queryprocessor.Type(queryprocessor.TypeContextFull)
value, err = queryprocessor.ToDBQueryType(dbQueryType)
assert.Nil(t, err)
assert.Equal(t, repository.Querytype(repository.QuerytypeContextFull), value)
}
func TestToDBQueryTypeArray(t *testing.T) {
inArr := []queryprocessor.Type{
queryprocessor.TypeJsonExtractor,
queryprocessor.TypeContextFull,
}
value, err := queryprocessor.ToDBQueryTypeArray(inArr)
assert.Nil(t, err)
assert.Equal(t, []repository.Querytype{
repository.QuerytypeJsonExtractor,
repository.QuerytypeContextFull,
}, value)
inArr = []queryprocessor.Type{
queryprocessor.Type(-1),
}
_, err = queryprocessor.ToDBQueryTypeArray(inArr)
assert.EqualError(t, err, "invalid database query type")
}
func TestToDBNullQueryType(t *testing.T) {
dbQueryType := queryprocessor.Type(queryprocessor.TypeJsonExtractor)
value, err := queryprocessor.ToDBNullQueryType(dbQueryType)
assert.Nil(t, err)
assert.Equal(t, repository.NullQuerytype{Valid: true, Querytype: repository.QuerytypeJsonExtractor}, value)
dbQueryType = queryprocessor.Type(-1)
_, err = queryprocessor.ToDBNullQueryType(dbQueryType)
assert.EqualError(t, err, "invalid database query type")
dbQueryType = queryprocessor.Type(queryprocessor.TypeContextFull)
value, err = queryprocessor.ToDBNullQueryType(dbQueryType)
assert.Nil(t, err)
assert.Equal(t, repository.NullQuerytype{Valid: true, Querytype: repository.QuerytypeContextFull}, value)
}
-98
View File
@@ -1,98 +0,0 @@
package queryqueue
import (
"context"
"queryorchestration/internal/database"
queryprocessor "queryorchestration/internal/query/processor"
)
func (q *Queue) getUnsyncedQueries() {
for _, query := range q.collectorQueries {
if q.isQuerySynced(query) {
continue
}
q.Add(query)
}
}
func (q *Queue) isQuerySynced(query *queryprocessor.Query) bool {
for _, result := range q.results {
if result.QueryID == query.ID && result.QueryVersion == query.Version {
return true
}
}
return false
}
func (c *Queue) getCollectorQueries(ctx context.Context) error {
if c.collectorQueries != nil {
return nil
}
id := database.MustToDBUUID(c.collector.ID)
queries, err := c.db.Queries.ListCollectorQueries(ctx, id)
if err != nil {
return err
}
cleanQueries := make([]*queryprocessor.Query, len(queries))
for index, dbQuery := range queries {
cleanQuery, err := queryprocessor.ParseDBCollectorQuery(dbQuery)
if err != nil {
return err
}
cleanQueries[index] = cleanQuery
}
c.collectorQueries = cleanQueries
return nil
}
func (q *Queue) Add(qu *queryprocessor.Query) {
dependentQueries := []*queryprocessor.Query{}
requiredIndex := -1
if q.unsyncedQueue == nil {
q.unsyncedQueue = []*queryprocessor.Query{}
} else {
for index, entry := range q.unsyncedQueue {
if entry.ID == qu.ID {
return
}
if qu.RequiredQueryIDs != nil {
for _, id := range *qu.RequiredQueryIDs {
if entry.ID == id {
requiredIndex = index
break
}
}
}
}
}
for _, entry := range q.collectorQueries {
if entry.RequiredQueryIDs != nil {
for _, id := range *entry.RequiredQueryIDs {
if qu.ID == id {
dependentQueries = append(dependentQueries, entry)
break
}
}
}
}
if requiredIndex != -1 {
q.unsyncedQueue = append((q.unsyncedQueue)[:requiredIndex+1], append([]*queryprocessor.Query{qu}, (q.unsyncedQueue)[requiredIndex+1:]...)...)
} else {
q.unsyncedQueue = append([]*queryprocessor.Query{qu}, q.unsyncedQueue...)
}
for _, entry := range dependentQueries {
q.Add(entry)
}
}
-143
View File
@@ -1,143 +0,0 @@
package queryqueue
import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/job/collector"
queryprocessor "queryorchestration/internal/query/processor"
"queryorchestration/internal/query/result"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/pashagolub/pgxmock/v3"
"github.com/stretchr/testify/assert"
)
func TestGetUnsyncedQueries(t *testing.T) {
queryOne := &queryprocessor.Query{
ID: uuid.New(),
Version: int32(1),
}
svc := Queue{
collectorQueries: []*queryprocessor.Query{
queryOne,
},
results: []*result.Result{
{ID: uuid.New(), QueryID: queryOne.ID, QueryVersion: queryOne.Version},
},
}
svc.getUnsyncedQueries()
assert.EqualExportedValues(t, []*queryprocessor.Query(nil), svc.unsyncedQueue)
svc.results = []*result.Result{}
svc.unsyncedQueue = []*queryprocessor.Query{}
svc.getUnsyncedQueries()
assert.EqualExportedValues(t, []*queryprocessor.Query{queryOne}, svc.unsyncedQueue)
}
func TestGetCollectorQueries(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
svc := Queue{
db: db,
collector: &collector.Collector{
ID: uuid.New(),
},
}
dbCollectorID := database.MustToDBUUID(svc.collector.ID)
collectorQueries := []*queryprocessor.Query{
{ID: uuid.New(), Type: queryprocessor.TypeContextFull, Version: int32(1)},
}
rows := pgxmock.NewRows([]string{"collectorId", "queryId", "type", "queryVersion", "requiredIds"})
for _, q := range collectorQueries {
dbID := database.MustToDBUUID(q.ID)
dbReqIDs := []pgtype.UUID{}
if q.RequiredQueryIDs != nil {
dbReqIDs = database.MustToDBUUIDArray(*q.RequiredQueryIDs)
}
ty, err := queryprocessor.ToDBQueryType(q.Type)
assert.Nil(t, err)
rows = rows.
AddRow(dbCollectorID, dbID, ty, q.Version, dbReqIDs)
}
pool.ExpectQuery("name: ListCollectorQueries :many").WithArgs(dbCollectorID).WillReturnRows(rows)
err = svc.getCollectorQueries(ctx)
assert.Nil(t, err)
assert.EqualExportedValues(t, collectorQueries, svc.collectorQueries)
}
func TestIsQuerySynced(t *testing.T) {
query := &queryprocessor.Query{
ID: uuid.New(),
Version: int32(1),
}
svc := Queue{
results: []*result.Result{
{QueryID: query.ID, QueryVersion: query.Version},
},
}
isSynced := svc.isQuerySynced(query)
assert.True(t, isSynced)
}
func TestIsQuerySyncedNoResult(t *testing.T) {
query := &queryprocessor.Query{
ID: uuid.New(),
Version: int32(1),
}
svc := Queue{
results: []*result.Result{},
}
isSynced := svc.isQuerySynced(query)
assert.False(t, isSynced)
}
func TestIsQuerySyncedOldResult(t *testing.T) {
query := &queryprocessor.Query{
ID: uuid.New(),
Version: int32(1),
}
svc := Queue{
results: []*result.Result{
{QueryID: query.ID, QueryVersion: query.Version - 1},
},
}
isSynced := svc.isQuerySynced(query)
assert.False(t, isSynced)
}
func TestIsQuerySyncedNewResult(t *testing.T) {
query := &queryprocessor.Query{
ID: uuid.New(),
Version: int32(1),
}
svc := Queue{
results: []*result.Result{
{QueryID: query.ID, QueryVersion: query.Version + 1},
},
}
isSynced := svc.isQuerySynced(query)
assert.False(t, isSynced)
}
-84
View File
@@ -1,84 +0,0 @@
package queryqueue
import (
"context"
"queryorchestration/internal/database"
queryprocessor "queryorchestration/internal/query/processor"
"queryorchestration/internal/query/result"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
)
func (q *Queue) Execute(ctx context.Context) error {
if q.unsyncedQueue == nil {
return nil
}
for _, query := range q.unsyncedQueue {
err := q.executeQuery(ctx, query)
if err != nil {
return err
}
}
q.unsyncedQueue = nil
return nil
}
func (q *Queue) executeQuery(ctx context.Context, qu *queryprocessor.Query) error {
values, err := q.getRequiredResults(ctx, qu.RequiredQueryIDs)
if err != nil {
return err
}
err = q.setResult(ctx, qu, values)
if err != nil {
return err
}
return nil
}
func (q *Queue) getRequiredResults(ctx context.Context, requiredQueryIDs *[]uuid.UUID) (*[]result.Value, error) {
var values *[]result.Value
if requiredQueryIDs != nil {
resultIDs := make([]pgtype.UUID, len(*requiredQueryIDs))
for index, id := range *requiredQueryIDs {
var queryVersion int32
for _, entry := range q.collectorQueries {
if entry.ID == id {
queryVersion = entry.Version
break
}
}
for _, entry := range q.results {
if entry.QueryID == id && entry.QueryVersion == queryVersion {
resultIDs[index] = database.MustToDBUUID(entry.ID)
break
}
}
}
resultValues, err := q.db.Queries.ListResultValuesByID(ctx, resultIDs)
if err != nil {
return nil, err
}
rValues := make([]result.Value, len(resultValues))
for index, r := range resultValues {
cleanValue, err := q.getResultValue(r)
if err != nil {
return nil, err
}
rValues[index] = cleanValue
}
values = &rValues
}
return values, nil
}
-175
View File
@@ -1,175 +0,0 @@
package queryqueue_test
import (
"context"
"fmt"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/job/collector"
queryprocessor "queryorchestration/internal/query/processor"
queryqueue "queryorchestration/internal/query/queue"
"queryorchestration/internal/query/result"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/pashagolub/pgxmock/v3"
"github.com/stretchr/testify/assert"
)
func TestExecute(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
coll := collector.Collector{
ID: uuid.New(),
}
dbCollectorID := database.MustToDBUUID(coll.ID)
queryOneID := uuid.New()
queryOneVersion := int32(1)
queryTwoID := uuid.New()
queryTwoVersion := int32(2)
queryThreeID := uuid.New()
queryThreeVersion := int32(3)
queryFourID := uuid.New()
queryFourVersion := int32(4)
queryFiveID := uuid.New()
queryFiveVersion := int32(5)
querySixID := uuid.New()
querySixVersion := int32(6)
contextID := uuid.New()
contextVersion := int32(1)
collectorQueries := []queryprocessor.Query{
{ID: contextID, Type: queryprocessor.TypeContextFull, Version: contextVersion},
{ID: queryOneID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{contextID}, Version: queryOneVersion},
{ID: queryTwoID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{queryOneID}, Version: queryTwoVersion},
{ID: queryThreeID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{queryOneID}, Version: queryThreeVersion},
{ID: queryFourID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{contextID}, Version: queryFourVersion},
{ID: queryFiveID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{querySixID}, Version: queryFiveVersion},
{ID: querySixID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{contextID}, Version: querySixVersion},
}
rows := pgxmock.NewRows([]string{"collectorId", "queryId", "type", "queryVersion", "requiredIds"})
for _, q := range collectorQueries {
dbID := database.MustToDBUUID(q.ID)
dbReqIDs := []pgtype.UUID{}
if q.RequiredQueryIDs != nil {
dbReqIDs = database.MustToDBUUIDArray(*q.RequiredQueryIDs)
}
ty, err := queryprocessor.ToDBQueryType(q.Type)
assert.Nil(t, err)
rows = rows.
AddRow(dbCollectorID, dbID, ty, q.Version, dbReqIDs)
}
pool.ExpectQuery("name: ListCollectorQueries :many").WithArgs(dbCollectorID).WillReturnRows(rows)
contextResultID := uuid.New()
results := []*result.Result{
{ID: contextResultID, QueryID: contextID, QueryVersion: contextVersion},
{ID: uuid.New(), QueryID: queryFourID, QueryVersion: queryFourVersion},
{ID: uuid.New(), QueryID: querySixID, QueryVersion: querySixVersion - 1},
{ID: uuid.New(), QueryID: queryOneID, QueryVersion: queryOneVersion - 1},
}
expectedQueries := []*queryprocessor.Query{
{ID: querySixID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{contextID}, Version: querySixVersion},
{ID: queryFiveID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{querySixID}, Version: queryFiveVersion},
{ID: queryOneID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{contextID}, Version: queryOneVersion},
{ID: queryThreeID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{queryOneID}, Version: queryThreeVersion},
{ID: queryTwoID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{queryOneID}, Version: queryTwoVersion},
}
docID := uuid.New()
cleanVersion := int32(1)
textVersion := int32(1)
q, err := queryqueue.New(ctx, &queryqueue.NewConfig{
db, &coll, results, docID, cleanVersion, textVersion,
})
assert.Nil(t, err)
assert.Equal(t, expectedQueries, q.GetQueue())
keyLayerOne := "key"
keyLayerTwo := "key5"
valueLayerTwo := "value"
valueLayerOne := fmt.Sprintf("{\"%s\":\"%s\"}", keyLayerTwo, valueLayerTwo)
valueContext := fmt.Sprintf("{\"%s\":%s}", keyLayerOne, valueLayerOne)
pool.ExpectQuery("name: ListResultValuesByID :many").WithArgs([]pgtype.UUID{database.MustToDBUUID(contextResultID)}).WillReturnRows(
pgxmock.NewRows([]string{"id", "queryId", "value"}).
AddRow(database.MustToDBUUID(contextResultID), database.MustToDBUUID(contextID), valueContext),
)
pool.ExpectQuery("name: GetQueryConfig :one").WithArgs(database.MustToDBUUID(querySixID), querySixVersion).WillReturnRows(
pgxmock.NewRows([]string{"id", "config"}).
AddRow(pgtype.UUID{}, []byte(fmt.Sprintf("{\"path\":\"%s\"}", keyLayerOne))),
)
pool.ExpectQuery("name: SetResult :one").WithArgs(database.MustToDBUUID(querySixID), database.MustToDBUUID(docID), valueLayerOne, cleanVersion, textVersion, querySixVersion).
WillReturnRows(
pgxmock.NewRows([]string{"id"}).AddRow(pgtype.UUID{}),
)
pool.ExpectQuery("name: ListResultValuesByID :many").WithArgs(pgxmock.AnyArg()).WillReturnRows(
pgxmock.NewRows([]string{"id", "queryId", "value"}).
AddRow(pgtype.UUID{}, database.MustToDBUUID(querySixID), valueLayerOne),
)
pool.ExpectQuery("name: GetQueryConfig :one").WithArgs(database.MustToDBUUID(queryFiveID), queryFiveVersion).WillReturnRows(
pgxmock.NewRows([]string{"id", "config"}).
AddRow(pgtype.UUID{}, []byte(fmt.Sprintf("{\"path\":\"%s\"}", keyLayerTwo))),
)
pool.ExpectQuery("name: SetResult :one").WithArgs(database.MustToDBUUID(queryFiveID), database.MustToDBUUID(docID), valueLayerTwo, cleanVersion, textVersion, queryFiveVersion).
WillReturnRows(
pgxmock.NewRows([]string{"id"}).AddRow(pgtype.UUID{}),
)
pool.ExpectQuery("name: ListResultValuesByID :many").WithArgs(pgxmock.AnyArg()).WillReturnRows(
pgxmock.NewRows([]string{"id", "queryId", "value"}).
AddRow(database.MustToDBUUID(contextResultID), database.MustToDBUUID(contextID), valueContext),
)
pool.ExpectQuery("name: GetQueryConfig :one").WithArgs(database.MustToDBUUID(queryOneID), queryOneVersion).WillReturnRows(
pgxmock.NewRows([]string{"id", "config"}).
AddRow(pgtype.UUID{}, []byte(fmt.Sprintf("{\"path\":\"%s\"}", keyLayerOne))),
)
pool.ExpectQuery("name: SetResult :one").WithArgs(database.MustToDBUUID(queryOneID), database.MustToDBUUID(docID), valueLayerOne, cleanVersion, textVersion, queryOneVersion).
WillReturnRows(
pgxmock.NewRows([]string{"id"}).AddRow(pgtype.UUID{}),
)
pool.ExpectQuery("name: ListResultValuesByID :many").WithArgs(pgxmock.AnyArg()).WillReturnRows(
pgxmock.NewRows([]string{"id", "queryId", "value"}).
AddRow(pgtype.UUID{}, database.MustToDBUUID(queryOneID), valueLayerOne),
)
pool.ExpectQuery("name: GetQueryConfig :one").WithArgs(database.MustToDBUUID(queryThreeID), queryThreeVersion).WillReturnRows(
pgxmock.NewRows([]string{"id", "config"}).
AddRow(pgtype.UUID{}, []byte(fmt.Sprintf("{\"path\":\"%s\"}", keyLayerTwo))),
)
pool.ExpectQuery("name: SetResult :one").WithArgs(database.MustToDBUUID(queryThreeID), database.MustToDBUUID(docID), valueLayerTwo, cleanVersion, textVersion, queryThreeVersion).
WillReturnRows(
pgxmock.NewRows([]string{"id"}).AddRow(pgtype.UUID{}),
)
pool.ExpectQuery("name: ListResultValuesByID :many").WithArgs(pgxmock.AnyArg()).WillReturnRows(
pgxmock.NewRows([]string{"id", "queryId", "value"}).
AddRow(pgtype.UUID{}, database.MustToDBUUID(queryOneID), valueLayerOne),
)
pool.ExpectQuery("name: GetQueryConfig :one").WithArgs(database.MustToDBUUID(queryTwoID), queryTwoVersion).WillReturnRows(
pgxmock.NewRows([]string{"id", "config"}).
AddRow(pgtype.UUID{}, []byte(fmt.Sprintf("{\"path\":\"%s\"}", keyLayerTwo))),
)
pool.ExpectQuery("name: SetResult :one").WithArgs(database.MustToDBUUID(queryTwoID), database.MustToDBUUID(docID), valueLayerTwo, cleanVersion, textVersion, queryTwoVersion).
WillReturnRows(
pgxmock.NewRows([]string{"id"}).AddRow(pgtype.UUID{}),
)
err = q.Execute(ctx)
assert.Nil(t, err)
}
@@ -1,85 +0,0 @@
package queryqueue
import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/pashagolub/pgxmock/v3"
"github.com/stretchr/testify/assert"
)
func TestExecute(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
expectedQueries := []*queryprocessor.Query{
{ID: uuid.New(), Type: queryprocessor.TypeContextFull, Version: int32(1)},
{ID: uuid.New(), Type: queryprocessor.TypeContextFull, Version: int32(2)},
}
q := &Queue{
unsyncedQueue: expectedQueries,
db: db,
documentId: uuid.New(),
cleanVersion: int32(1),
textVersion: int32(2),
}
pool.ExpectQuery("name: SetResult :one").WithArgs(database.MustToDBUUID(expectedQueries[0].ID), database.MustToDBUUID(q.documentId), pgxmock.AnyArg(), q.cleanVersion, q.textVersion, expectedQueries[0].Version).
WillReturnRows(
pgxmock.NewRows([]string{"id"}).AddRow(pgtype.UUID{}),
)
pool.ExpectQuery("name: SetResult :one").WithArgs(database.MustToDBUUID(expectedQueries[1].ID), database.MustToDBUUID(q.documentId), pgxmock.AnyArg(), q.cleanVersion, q.textVersion, expectedQueries[1].Version).
WillReturnRows(
pgxmock.NewRows([]string{"id"}).AddRow(pgtype.UUID{}),
)
err = q.Execute(ctx)
assert.Nil(t, err)
}
func TestExecuteQuery(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
qu := &queryprocessor.Query{ID: uuid.New(), Type: queryprocessor.TypeContextFull, Version: int32(1)}
q := &Queue{
db: db,
documentId: uuid.New(),
cleanVersion: int32(1),
textVersion: int32(2),
}
pool.ExpectQuery("name: SetResult :one").WithArgs(database.MustToDBUUID(qu.ID), database.MustToDBUUID(q.documentId), pgxmock.AnyArg(), q.cleanVersion, q.textVersion, qu.Version).
WillReturnRows(
pgxmock.NewRows([]string{"id"}).AddRow(pgtype.UUID{}),
)
err = q.executeQuery(ctx, qu)
assert.Nil(t, err)
}
-73
View File
@@ -1,73 +0,0 @@
package queryqueue
import (
"context"
"fmt"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
"queryorchestration/internal/query/result"
contextfull "queryorchestration/internal/query/types/contextFull"
jsonextractor "queryorchestration/internal/query/types/jsonExtractor"
)
func (q *Queue) setResult(ctx context.Context, qu *queryprocessor.Query, resultValues *[]result.Value) error {
processor, err := q.getProcessor(qu.Type)
if err != nil {
return err
}
value, err := processor.Process(ctx, qu, resultValues)
if err != nil {
return err
}
id, err := result.Store(ctx, q.db.Queries, &result.ResultStore{
QueryID: qu.ID,
DocumentID: q.documentId,
Value: value,
CleanVersion: q.cleanVersion,
TextVersion: q.textVersion,
QueryVersion: qu.Version,
})
if err != nil {
return err
}
q.results = append(q.results, &result.Result{
ID: id,
QueryID: qu.ID,
QueryVersion: qu.Version,
})
return nil
}
func (q *Queue) getProcessor(queryType queryprocessor.Type) (queryprocessor.Processor, error) {
switch queryType {
case queryprocessor.TypeJsonExtractor:
return jsonextractor.NewExtractor(q.db), nil
case queryprocessor.TypeContextFull:
return contextfull.NewExtractor(), nil
default:
return nil, fmt.Errorf("attempting to process invalid query type")
}
}
func (q *Queue) getResultValue(res *repository.ListResultValuesByIDRow) (result.Value, error) {
var queryType queryprocessor.Type
for _, qu := range q.collectorQueries {
if qu.ID == database.MustToUUID(res.Queryid) {
queryType = qu.Type
}
}
switch queryType {
case queryprocessor.TypeJsonExtractor:
return jsonextractor.NewResult(res.Value), nil
case queryprocessor.TypeContextFull:
return contextfull.NewResult(res.Value), nil
default:
return nil, fmt.Errorf("attempting to process invalid query type")
}
}
@@ -1,74 +0,0 @@
package queryqueue
import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
"queryorchestration/internal/query/result"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/pashagolub/pgxmock/v3"
"github.com/stretchr/testify/assert"
)
func TestSetResult(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
q := &Queue{
db: db,
documentId: uuid.New(),
cleanVersion: int32(1),
textVersion: int32(2),
}
qu := &queryprocessor.Query{ID: uuid.New(), Type: queryprocessor.TypeContextFull, Version: int32(1)}
resultValues := []result.Value{}
pool.ExpectQuery("name: SetResult :one").WithArgs(database.MustToDBUUID(qu.ID), database.MustToDBUUID(q.documentId), pgxmock.AnyArg(), q.cleanVersion, q.textVersion, qu.Version).
WillReturnRows(
pgxmock.NewRows([]string{"id"}).AddRow(pgtype.UUID{}),
)
err = q.setResult(ctx, qu, &resultValues)
assert.Nil(t, err)
}
func TestGetProcessor(t *testing.T) {
q := Queue{}
qType := queryprocessor.Type(queryprocessor.TypeContextFull)
processor, err := q.getProcessor(qType)
assert.Nil(t, err)
assert.NotNil(t, processor)
}
func TestGetResultValue(t *testing.T) {
result := &repository.ListResultValuesByIDRow{
Queryid: database.MustToDBUUID(uuid.New()),
Value: "EXAMPLE_VALUE",
}
q := &Queue{
collectorQueries: []*queryprocessor.Query{
{ID: database.MustToUUID(result.Queryid), Type: queryprocessor.TypeContextFull},
},
}
value, err := q.getResultValue(result)
assert.Nil(t, err)
assert.NotNil(t, value)
}
-55
View File
@@ -1,55 +0,0 @@
package queryqueue
import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/job/collector"
queryprocessor "queryorchestration/internal/query/processor"
"queryorchestration/internal/query/result"
"github.com/google/uuid"
)
type Queue struct {
unsyncedQueue []*queryprocessor.Query
collectorQueries []*queryprocessor.Query
results []*result.Result
collector *collector.Collector
db *database.Connection
documentId uuid.UUID
cleanVersion int32
textVersion int32
}
type NewConfig struct {
DB *database.Connection
Collector *collector.Collector
Results []*result.Result
DocumentID uuid.UUID
CleanVersion int32
TextVersion int32
}
func New(ctx context.Context, cfg *NewConfig) (*Queue, error) {
queue := Queue{
db: cfg.DB,
results: cfg.Results,
collector: cfg.Collector,
documentId: cfg.DocumentID,
cleanVersion: cfg.CleanVersion,
textVersion: cfg.TextVersion,
}
err := queue.getCollectorQueries(ctx)
if err != nil {
return nil, err
}
queue.getUnsyncedQueries()
return &queue, nil
}
func (q *Queue) GetQueue() []*queryprocessor.Query {
return q.unsyncedQueue
}
-135
View File
@@ -1,135 +0,0 @@
package queryqueue_test
import (
"context"
"errors"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/job/collector"
queryprocessor "queryorchestration/internal/query/processor"
queryqueue "queryorchestration/internal/query/queue"
"queryorchestration/internal/query/result"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/pashagolub/pgxmock/v3"
"github.com/stretchr/testify/assert"
)
func TestService(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
coll := collector.Collector{
ID: uuid.New(),
}
dbCollectorID := database.MustToDBUUID(coll.ID)
queryOneID := uuid.New()
queryOneVersion := int32(1)
queryTwoID := uuid.New()
queryTwoVersion := int32(2)
queryThreeID := uuid.New()
queryThreeVersion := int32(3)
queryFourID := uuid.New()
queryFourVersion := int32(4)
queryFiveID := uuid.New()
queryFiveVersion := int32(5)
querySixID := uuid.New()
querySixVersion := int32(6)
contextID := uuid.New()
contextVersion := int32(1)
collectorQueries := []queryprocessor.Query{
{ID: contextID, Type: queryprocessor.TypeContextFull, Version: contextVersion},
{ID: queryOneID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{contextID}, Version: queryOneVersion},
{ID: queryTwoID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{queryOneID}, Version: queryTwoVersion},
{ID: queryThreeID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{queryOneID}, Version: queryThreeVersion},
{ID: queryFourID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{contextID}, Version: queryFourVersion},
{ID: queryFiveID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{querySixID}, Version: queryFiveVersion},
{ID: querySixID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{contextID}, Version: querySixVersion},
}
rows := pgxmock.NewRows([]string{"collectorId", "queryId", "type", "queryVersion", "requiredIds"})
for _, q := range collectorQueries {
dbID := database.MustToDBUUID(q.ID)
dbReqIDs := []pgtype.UUID{}
if q.RequiredQueryIDs != nil {
dbReqIDs = database.MustToDBUUIDArray(*q.RequiredQueryIDs)
}
ty, err := queryprocessor.ToDBQueryType(q.Type)
assert.Nil(t, err)
rows = rows.
AddRow(dbCollectorID, dbID, ty, q.Version, dbReqIDs)
}
pool.ExpectQuery("name: ListCollectorQueries :many").WithArgs(dbCollectorID).WillReturnRows(rows)
contextResultID := uuid.New()
results := []*result.Result{
{ID: contextResultID, QueryID: contextID, QueryVersion: contextVersion},
{ID: uuid.New(), QueryID: queryFourID, QueryVersion: queryFourVersion},
{ID: uuid.New(), QueryID: querySixID, QueryVersion: querySixVersion - 1},
{ID: uuid.New(), QueryID: queryOneID, QueryVersion: queryOneVersion - 1},
}
expectedQueries := []*queryprocessor.Query{
{ID: querySixID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{contextID}, Version: querySixVersion},
{ID: queryFiveID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{querySixID}, Version: queryFiveVersion},
{ID: queryOneID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{contextID}, Version: queryOneVersion},
{ID: queryThreeID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{queryOneID}, Version: queryThreeVersion},
{ID: queryTwoID, Type: queryprocessor.TypeJsonExtractor, RequiredQueryIDs: &[]uuid.UUID{queryOneID}, Version: queryTwoVersion},
}
docID := uuid.New()
cleanVersion := int32(1)
textVersion := int32(1)
q, err := queryqueue.New(ctx, &queryqueue.NewConfig{
db, &coll, results, docID, cleanVersion, textVersion,
})
assert.Nil(t, err)
assert.Equal(t, expectedQueries, q.GetQueue())
}
func TestQueueFail(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
coll := collector.Collector{
ID: uuid.New(),
}
dbCollectorID := database.MustToDBUUID(coll.ID)
dbErr := "database failure"
pool.ExpectQuery("name: ListCollectorQueries :many").WithArgs(dbCollectorID).
WillReturnError(errors.New(dbErr))
results := []*result.Result{}
docID := uuid.New()
cleanVersion := int32(1)
textVersion := int32(1)
_, err = queryqueue.New(ctx, &queryqueue.NewConfig{
db, &coll, results, docID, cleanVersion, textVersion,
})
assert.EqualError(t, err, dbErr)
}
+48
View File
@@ -0,0 +1,48 @@
package result
import (
"context"
"fmt"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
resultprocessor "queryorchestration/internal/query/result/processor"
contextfull "queryorchestration/internal/query/types/contextFull"
jsonextractor "queryorchestration/internal/query/types/jsonExtractor"
"github.com/google/uuid"
)
type GetValueWithVersionParams struct {
Type resultprocessor.Type
QueryID uuid.UUID
DocumentID uuid.UUID
QueryVersion int32
MinCleanVersion int32
MinTextVersion int32
}
func (s *Service) GetValueWithVersion(ctx context.Context, params *GetValueWithVersionParams) (resultprocessor.Value, error) {
res, err := s.db.Queries.GetResultValueWithVersion(ctx, &repository.GetResultValueWithVersionParams{
Queryid: database.MustToDBUUID(params.QueryID),
Queryversion: params.QueryVersion,
Documentid: database.MustToDBUUID(params.DocumentID),
Cleanversion: params.MinCleanVersion,
Textversion: params.MinTextVersion,
})
if err != nil {
return nil, err
}
return getValueByType(params.Type, res.Value)
}
func getValueByType(t resultprocessor.Type, value string) (resultprocessor.Value, error) {
switch t {
case resultprocessor.TypeJsonExtractor:
return jsonextractor.NewResult(value), nil
case resultprocessor.TypeContextFull:
return contextfull.NewResult(value), nil
default:
return nil, fmt.Errorf("attempting to process invalid query type")
}
}
+64
View File
@@ -0,0 +1,64 @@
package result
import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
resultprocessor "queryorchestration/internal/query/result/processor"
jsonextractor "queryorchestration/internal/query/types/jsonExtractor"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/pashagolub/pgxmock/v3"
"github.com/stretchr/testify/assert"
)
func TestGetValueByType(t *testing.T) {
_, err := getValueByType(resultprocessor.Type(-1), "example_val")
assert.Error(t, err)
pro, err := getValueByType(resultprocessor.TypeContextFull, "example_context")
assert.Nil(t, err)
assert.NotNil(t, pro)
assert.Equal(t, "example_context", pro.GetStoreValue())
pro, err = getValueByType(resultprocessor.TypeJsonExtractor, "example_json")
assert.Nil(t, err)
assert.NotNil(t, pro)
assert.Equal(t, "example_json", pro.GetStoreValue())
}
func TestGetValueWithVersion(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
svc := New(db)
params := &GetValueWithVersionParams{
Type: resultprocessor.TypeJsonExtractor,
QueryID: uuid.New(),
DocumentID: uuid.New(),
QueryVersion: 1,
MinCleanVersion: 2,
MinTextVersion: 3,
}
pool.ExpectQuery("name: GetResultValueWithVersion :one").WithArgs(database.MustToDBUUID(params.QueryID), params.QueryVersion, database.MustToDBUUID(params.DocumentID), params.MinCleanVersion, params.MinTextVersion).
WillReturnRows(
pgxmock.NewRows([]string{"id", "value"}).
AddRow(pgtype.UUID{}, "example_value"),
)
val, err := svc.GetValueWithVersion(ctx, params)
assert.Nil(t, err)
v := jsonextractor.NewResult("example_value")
assert.Equal(t, v, val)
assert.Equal(t, "example_value", v.GetStoreValue())
}
+52
View File
@@ -0,0 +1,52 @@
package result
import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
resultprocessor "queryorchestration/internal/query/result/processor"
"github.com/google/uuid"
)
type ListQueryRequirementValuesParams struct {
QueryID uuid.UUID
DocumentID uuid.UUID
QueryVersion int32
MinCleanVersion int32
MinTextVersion int32
}
func (s *Service) ListQueryRequirementValues(ctx context.Context, params *ListQueryRequirementValuesParams) (*[]resultprocessor.Value, error) {
qResults, err := s.db.Queries.ListQueryRequirementValues(ctx, &repository.ListQueryRequirementValuesParams{
Queryid: database.MustToDBUUID(params.QueryID),
Documentid: database.MustToDBUUID(params.DocumentID),
Addedversion: params.QueryVersion,
Cleanversion: params.MinCleanVersion,
Textversion: params.MinTextVersion,
})
if err != nil {
return nil, err
}
return parseQueryRequirementValueArray(qResults)
}
func parseQueryRequirementValueArray(v []*repository.ListQueryRequirementValuesRow) (*[]resultprocessor.Value, error) {
values := make([]resultprocessor.Value, len(v))
for index, r := range v {
qType, err := resultprocessor.ParseDBType(r.Type)
if err != nil {
return nil, err
}
cleanValue, err := getValueByType(qType, r.Value)
if err != nil {
return nil, err
}
values[index] = cleanValue
}
return &values, nil
}
+68
View File
@@ -0,0 +1,68 @@
package result
import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
resultprocessor "queryorchestration/internal/query/result/processor"
jsonextractor "queryorchestration/internal/query/types/jsonExtractor"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/pashagolub/pgxmock/v3"
"github.com/stretchr/testify/assert"
)
func TestListQueryRequirementValues(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
svc := Service{
db: db,
}
params := &ListQueryRequirementValuesParams{
QueryID: uuid.New(),
QueryVersion: 1,
DocumentID: uuid.New(),
MinCleanVersion: 2,
MinTextVersion: 3,
}
pool.ExpectQuery("name: ListQueryRequirementValues :many").WithArgs(database.MustToDBUUID(params.QueryID), params.QueryVersion, database.MustToDBUUID(params.DocumentID), params.MinCleanVersion, params.MinTextVersion).
WillReturnRows(
pgxmock.NewRows([]string{"queryId", "value", "type"}).
AddRow(pgtype.UUID{}, "example_value", repository.QuerytypeJsonExtractor),
)
val, err := svc.ListQueryRequirementValues(ctx, params)
assert.Nil(t, err)
assert.ElementsMatch(t, []resultprocessor.Value{
jsonextractor.NewResult("example_value"),
}, *val)
}
func TestParseQueryRequirementValueArray(t *testing.T) {
in := []*repository.ListQueryRequirementValuesRow{
{
Queryid: database.MustToDBUUID(uuid.New()),
Value: "example_value",
Type: repository.QuerytypeJsonExtractor,
},
}
out, err := parseQueryRequirementValueArray(in)
assert.Nil(t, err)
assert.ElementsMatch(t, []resultprocessor.Value{
jsonextractor.NewResult("example_value"),
}, *out)
}
-14
View File
@@ -1,14 +0,0 @@
package result
import (
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
)
func Parse(dbQuery *repository.ListResultsByDocumentIDRow) *Result {
return &Result{
ID: database.MustToUUID(dbQuery.ID),
QueryID: database.MustToUUID(dbQuery.Queryid),
QueryVersion: dbQuery.Queryversion,
}
}
-24
View File
@@ -1,24 +0,0 @@
package result_test
import (
"queryorchestration/internal/database/repository"
"queryorchestration/internal/query/result"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/stretchr/testify/assert"
)
func TestParseResultValue(t *testing.T) {
dbResult := repository.ListResultsByDocumentIDRow{
ID: pgtype.UUID{},
Queryid: pgtype.UUID{},
Queryversion: int32(1),
}
value := result.Parse(&dbResult)
assert.Equal(t, dbResult.Queryversion, value.QueryVersion)
assert.Equal(t, uuid.Nil, value.ID)
assert.Equal(t, uuid.Nil, value.QueryID)
}
+70
View File
@@ -0,0 +1,70 @@
package result
import (
"context"
"errors"
"fmt"
resultprocessor "queryorchestration/internal/query/result/processor"
contextfull "queryorchestration/internal/query/types/contextFull"
jsonextractor "queryorchestration/internal/query/types/jsonExtractor"
"github.com/google/uuid"
)
type Process struct {
DocumentID uuid.UUID
MinCleanVersion int32
MinTextVersion int32
Query *resultprocessor.Query
}
func (s *Service) Process(ctx context.Context, p *Process) (resultprocessor.Value, error) {
values, err := s.listRequiredValues(ctx, p)
if err != nil {
return nil, err
}
processor, err := s.getProcessor(p.Query.Type)
if err != nil {
return nil, err
}
val, err := processor.Process(ctx, p.Query, values)
if err != nil {
return nil, err
}
return getValueByType(p.Query.Type, val)
}
func (s *Service) listRequiredValues(ctx context.Context, p *Process) (*[]resultprocessor.Value, error) {
if p == nil || p.Query == nil || p.Query.RequiredQueryIDs == nil || len(*p.Query.RequiredQueryIDs) == 0 {
return nil, nil
}
values, err := s.ListQueryRequirementValues(ctx, &ListQueryRequirementValuesParams{
QueryID: p.Query.ID,
QueryVersion: p.Query.Version,
DocumentID: p.DocumentID,
MinCleanVersion: p.MinCleanVersion,
MinTextVersion: p.MinTextVersion,
})
if err != nil {
return nil, err
} else if values == nil || len(*values) != len(*p.Query.RequiredQueryIDs) {
return nil, errors.New("document not synced")
}
return values, nil
}
func (s *Service) getProcessor(queryType resultprocessor.Type) (resultprocessor.Processor, error) {
switch queryType {
case resultprocessor.TypeJsonExtractor:
return jsonextractor.NewExtractor(s.db), nil
case resultprocessor.TypeContextFull:
return contextfull.NewExtractor(), nil
default:
return nil, fmt.Errorf("attempting to process invalid query type")
}
}
+143
View File
@@ -0,0 +1,143 @@
package result
import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
resultprocessor "queryorchestration/internal/query/result/processor"
jsonextractor "queryorchestration/internal/query/types/jsonExtractor"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/pashagolub/pgxmock/v3"
"github.com/stretchr/testify/assert"
)
func TestProcess(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
svc := Service{
db: db,
}
cfg := "{\"path\":\"examplekey\"}"
params := Process{
DocumentID: uuid.New(),
MinCleanVersion: 1,
MinTextVersion: 3,
Query: &resultprocessor.Query{
ID: uuid.New(),
Version: 2,
Config: &cfg,
RequiredQueryIDs: &[]uuid.UUID{
uuid.New(),
},
},
}
pool.ExpectQuery("name: ListQueryRequirementValues :many").WithArgs(database.MustToDBUUID(params.Query.ID), params.Query.Version, database.MustToDBUUID(params.DocumentID), params.MinCleanVersion, params.MinTextVersion).
WillReturnRows(
pgxmock.NewRows([]string{"queryId", "value", "type"}).
AddRow(database.MustToDBUUID((*params.Query.RequiredQueryIDs)[0]), "{\"examplekey\":\"example_value\"}", repository.QuerytypeContextFull),
)
pool.ExpectQuery("name: GetQueryConfig :one").WithArgs(database.MustToDBUUID(params.Query.ID), params.Query.Version).WillReturnRows(
pgxmock.NewRows([]string{"id", "config"}).
AddRow(pgtype.UUID{}, []byte(cfg)),
)
val, err := svc.Process(ctx, &params)
assert.Nil(t, err)
assert.NotNil(t, val)
assert.Equal(t, "example_value", val.GetStoreValue())
}
func TestListRequiredValue(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
svc := Service{
db: db,
}
pr, err := svc.listRequiredValues(ctx, nil)
assert.Nil(t, err)
assert.Nil(t, pr)
pr, err = svc.listRequiredValues(ctx, &Process{})
assert.Nil(t, err)
assert.Nil(t, pr)
pr, err = svc.listRequiredValues(ctx, &Process{
Query: &resultprocessor.Query{},
})
assert.Nil(t, err)
assert.Nil(t, pr)
pr, err = svc.listRequiredValues(ctx, &Process{
Query: &resultprocessor.Query{
RequiredQueryIDs: &[]uuid.UUID{},
},
})
assert.Nil(t, err)
assert.Nil(t, pr)
params := Process{
DocumentID: uuid.New(),
MinCleanVersion: 1,
MinTextVersion: 3,
Query: &resultprocessor.Query{
ID: uuid.New(),
Version: 2,
RequiredQueryIDs: &[]uuid.UUID{
uuid.New(),
},
},
}
pool.ExpectQuery("name: ListQueryRequirementValues :many").WithArgs(database.MustToDBUUID(params.Query.ID), params.Query.Version, database.MustToDBUUID(params.DocumentID), params.MinCleanVersion, params.MinTextVersion).
WillReturnRows(
pgxmock.NewRows([]string{"queryId", "value", "type"}).
AddRow(database.MustToDBUUID((*params.Query.RequiredQueryIDs)[0]), "example_value", repository.QuerytypeJsonExtractor),
)
pr, err = svc.listRequiredValues(ctx, &params)
assert.Nil(t, err)
assert.ElementsMatch(t, []resultprocessor.Value{
jsonextractor.NewResult("example_value"),
}, *pr)
}
func TestGetProcessor(t *testing.T) {
svc := Service{}
pr, err := svc.getProcessor(resultprocessor.TypeJsonExtractor)
assert.Nil(t, err)
assert.NotNil(t, pr)
pr, err = svc.getProcessor(resultprocessor.TypeContextFull)
assert.Nil(t, err)
assert.NotNil(t, pr)
_, err = svc.getProcessor(resultprocessor.Type(-1))
assert.Error(t, err)
}
@@ -1,4 +1,4 @@
package queryprocessor
package resultprocessor
import (
"fmt"
@@ -84,3 +84,48 @@ func ParseDBCollectorQuery(q *repository.Collectorquerydependencytree) (*Query,
RequiredQueryIDs: reqQueryIDs,
}, nil
}
func ParseFullQuery(qs *repository.Fullactivequery) (*Query, error) {
if qs == nil {
return nil, nil
}
qt, err := ParseDBType(qs.Type)
if err != nil {
return nil, err
}
var rids *[]uuid.UUID
if len(qs.Requiredids) > 0 {
r := database.MustToUUIDArray(qs.Requiredids)
rids = &r
}
var cfg *string
if qs.Config != nil {
c := string(qs.Config)
cfg = &c
}
return &Query{
ID: database.MustToUUID(qs.ID),
Type: qt,
Version: qs.Activeversion,
RequiredQueryIDs: rids,
Config: cfg,
}, nil
}
func ParseFullQueryArray(qs []*repository.Fullactivequery) ([]*Query, error) {
parsed := make([]*Query, len(qs))
for i, q := range qs {
p, err := ParseFullQuery(q)
if err != nil {
return nil, err
}
parsed[i] = p
}
return parsed, nil
}
@@ -0,0 +1,197 @@
package resultprocessor_test
import (
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
resultprocessor "queryorchestration/internal/query/result/processor"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/stretchr/testify/assert"
)
func TestParseDBCollectorQuery(t *testing.T) {
dbResult := repository.Collectorquerydependencytree{
Collectorid: pgtype.UUID{},
Queryid: pgtype.UUID{},
Requiredids: []pgtype.UUID{},
Type: repository.QuerytypeJsonExtractor,
Queryversion: 1,
}
value, err := resultprocessor.ParseDBCollectorQuery(&dbResult)
assert.Nil(t, err)
assert.Equal(t, uuid.Nil, value.ID)
assert.Nil(t, value.RequiredQueryIDs)
assert.Equal(t, int32(1), value.Version)
assert.Equal(t, resultprocessor.Type(resultprocessor.TypeJsonExtractor), value.Type)
dbResult.Type = repository.Querytype("")
_, err = resultprocessor.ParseDBCollectorQuery(&dbResult)
assert.EqualError(t, err, "invalid database query type")
}
func TestParseDBNullType(t *testing.T) {
qType := repository.NullQuerytype{Valid: true, Querytype: repository.QuerytypeJsonExtractor}
value, err := resultprocessor.ParseDBNullType(qType)
assert.Nil(t, err)
assert.Equal(t, resultprocessor.Type(resultprocessor.TypeJsonExtractor), value)
qType = repository.NullQuerytype{}
_, err = resultprocessor.ParseDBNullType(qType)
assert.EqualError(t, err, "invalid database query type")
qType = repository.NullQuerytype{Valid: true}
_, err = resultprocessor.ParseDBNullType(qType)
assert.EqualError(t, err, "invalid database query type")
}
func TestParseDBType(t *testing.T) {
qType := repository.QuerytypeJsonExtractor
value, err := resultprocessor.ParseDBType(qType)
assert.Nil(t, err)
assert.Equal(t, resultprocessor.Type(resultprocessor.TypeJsonExtractor), value)
qType = repository.QuerytypeContextFull
value, err = resultprocessor.ParseDBType(qType)
assert.Nil(t, err)
assert.Equal(t, resultprocessor.Type(resultprocessor.TypeContextFull), value)
}
func TestToDBQueryType(t *testing.T) {
dbQueryType := resultprocessor.Type(resultprocessor.TypeJsonExtractor)
value, err := resultprocessor.ToDBQueryType(dbQueryType)
assert.Nil(t, err)
assert.Equal(t, repository.Querytype(repository.QuerytypeJsonExtractor), value)
dbQueryType = resultprocessor.Type(-1)
_, err = resultprocessor.ToDBQueryType(dbQueryType)
assert.EqualError(t, err, "invalid database query type")
dbQueryType = resultprocessor.Type(resultprocessor.TypeContextFull)
value, err = resultprocessor.ToDBQueryType(dbQueryType)
assert.Nil(t, err)
assert.Equal(t, repository.Querytype(repository.QuerytypeContextFull), value)
}
func TestToDBQueryTypeArray(t *testing.T) {
inArr := []resultprocessor.Type{
resultprocessor.TypeJsonExtractor,
resultprocessor.TypeContextFull,
}
value, err := resultprocessor.ToDBQueryTypeArray(inArr)
assert.Nil(t, err)
assert.Equal(t, []repository.Querytype{
repository.QuerytypeJsonExtractor,
repository.QuerytypeContextFull,
}, value)
inArr = []resultprocessor.Type{
resultprocessor.Type(-1),
}
_, err = resultprocessor.ToDBQueryTypeArray(inArr)
assert.EqualError(t, err, "invalid database query type")
}
func TestToDBNullQueryType(t *testing.T) {
dbQueryType := resultprocessor.Type(resultprocessor.TypeJsonExtractor)
value, err := resultprocessor.ToDBNullQueryType(dbQueryType)
assert.Nil(t, err)
assert.Equal(t, repository.NullQuerytype{Valid: true, Querytype: repository.QuerytypeJsonExtractor}, value)
dbQueryType = resultprocessor.Type(-1)
_, err = resultprocessor.ToDBNullQueryType(dbQueryType)
assert.EqualError(t, err, "invalid database query type")
dbQueryType = resultprocessor.Type(resultprocessor.TypeContextFull)
value, err = resultprocessor.ToDBNullQueryType(dbQueryType)
assert.Nil(t, err)
assert.Equal(t, repository.NullQuerytype{Valid: true, Querytype: repository.QuerytypeContextFull}, value)
}
func TestParseFullQuery(t *testing.T) {
var q *repository.Fullactivequery
out, err := resultprocessor.ParseFullQuery(q)
assert.Nil(t, err)
assert.Nil(t, out)
q = &repository.Fullactivequery{
ID: database.MustToDBUUID(uuid.New()),
Type: repository.QuerytypeContextFull,
Activeversion: 1,
Latestversion: 2,
}
out, err = resultprocessor.ParseFullQuery(q)
assert.Nil(t, err)
assert.EqualExportedValues(t, &resultprocessor.Query{
ID: database.MustToUUID(q.ID),
Type: resultprocessor.TypeContextFull,
Version: 1,
}, out)
q = &repository.Fullactivequery{
ID: database.MustToDBUUID(uuid.New()),
Type: repository.QuerytypeContextFull,
Activeversion: 1,
Latestversion: 2,
Requiredids: []pgtype.UUID{},
}
out, err = resultprocessor.ParseFullQuery(q)
assert.Nil(t, err)
assert.EqualExportedValues(t, &resultprocessor.Query{
ID: database.MustToUUID(q.ID),
Type: resultprocessor.TypeContextFull,
Version: 1,
}, out)
q = &repository.Fullactivequery{
ID: database.MustToDBUUID(uuid.New()),
Type: repository.QuerytypeContextFull,
Activeversion: 1,
Latestversion: 2,
Config: []byte("hello"),
Requiredids: []pgtype.UUID{
database.MustToDBUUID(uuid.New()),
},
}
out, err = resultprocessor.ParseFullQuery(q)
assert.Nil(t, err)
cfg := "hello"
assert.EqualExportedValues(t, &resultprocessor.Query{
ID: database.MustToUUID(q.ID),
Type: resultprocessor.TypeContextFull,
Version: 1,
Config: &cfg,
RequiredQueryIDs: &[]uuid.UUID{database.MustToUUID(q.Requiredids[0])},
}, out)
}
func TestParseFullQueryArray(t *testing.T) {
var q []*repository.Fullactivequery
out, err := resultprocessor.ParseFullQueryArray(q)
assert.Nil(t, err)
assert.ElementsMatch(t, []*resultprocessor.Query{}, out)
q = []*repository.Fullactivequery{
{
ID: database.MustToDBUUID(uuid.New()),
Type: repository.QuerytypeContextFull,
Activeversion: 1,
Latestversion: 2,
},
}
out, err = resultprocessor.ParseFullQueryArray(q)
assert.Nil(t, err)
assert.EqualExportedValues(t, []*resultprocessor.Query{
{
ID: database.MustToUUID(q[0].ID),
Type: resultprocessor.TypeContextFull,
Version: 1,
},
}, out)
}
@@ -1,12 +1,16 @@
package queryprocessor
package resultprocessor
import (
"context"
"queryorchestration/internal/query/result"
"github.com/google/uuid"
)
type Value interface {
GetValue(ctx context.Context) (string, error)
GetStoreValue() string
}
type Type int
const (
@@ -76,5 +80,5 @@ type Updator interface {
}
type Processor interface {
Process(ctx context.Context, query *Query, values *[]result.Value) (string, error)
Process(ctx context.Context, query *Query, values *[]Value) (string, error)
}
@@ -1,7 +1,7 @@
package queryprocessor_test
package resultprocessor_test
import (
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
"testing"
"github.com/google/uuid"
@@ -9,7 +9,7 @@ import (
)
func TestCreateGetConfig(t *testing.T) {
entity := queryprocessor.Create{}
entity := resultprocessor.Create{}
assert.Nil(t, entity.GetConfig())
@@ -20,7 +20,7 @@ func TestCreateGetConfig(t *testing.T) {
}
func TestCreateSetConfig(t *testing.T) {
entity := queryprocessor.Create{}
entity := resultprocessor.Create{}
assert.Nil(t, entity.Config)
@@ -30,7 +30,7 @@ func TestCreateSetConfig(t *testing.T) {
}
func TestUpdateGetConfig(t *testing.T) {
entity := queryprocessor.Update{}
entity := resultprocessor.Update{}
assert.Nil(t, entity.GetConfig())
@@ -41,7 +41,7 @@ func TestUpdateGetConfig(t *testing.T) {
}
func TestUpdateSetConfig(t *testing.T) {
entity := queryprocessor.Update{}
entity := resultprocessor.Update{}
assert.Nil(t, entity.Config)
@@ -51,7 +51,7 @@ func TestUpdateSetConfig(t *testing.T) {
}
func TestCreateGetRequiredQueryIDs(t *testing.T) {
entity := queryprocessor.Create{}
entity := resultprocessor.Create{}
assert.Nil(t, entity.GetRequiredQueryIDs())
@@ -62,7 +62,7 @@ func TestCreateGetRequiredQueryIDs(t *testing.T) {
}
func TestCreateSetRequiredQueryIDs(t *testing.T) {
entity := queryprocessor.Create{}
entity := resultprocessor.Create{}
assert.Nil(t, entity.RequiredQueryIDs)
@@ -72,7 +72,7 @@ func TestCreateSetRequiredQueryIDs(t *testing.T) {
}
func TestUpdateGetRequiredQueryIDs(t *testing.T) {
entity := queryprocessor.Update{}
entity := resultprocessor.Update{}
assert.Nil(t, entity.GetRequiredQueryIDs())
@@ -83,7 +83,7 @@ func TestUpdateGetRequiredQueryIDs(t *testing.T) {
}
func TestUpdateSetRequiredQueryIDs(t *testing.T) {
entity := queryprocessor.Update{}
entity := resultprocessor.Update{}
assert.Nil(t, entity.RequiredQueryIDs)
+5 -28
View File
@@ -1,9 +1,7 @@
package result
import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
"github.com/google/uuid"
)
@@ -14,33 +12,12 @@ type Result struct {
QueryVersion int32
}
type Value interface {
GetValue(ctx context.Context) (string, error)
type Service struct {
db *database.Connection
}
type ResultStore struct {
QueryID uuid.UUID
DocumentID uuid.UUID
Value string
CleanVersion int32
TextVersion int32
QueryVersion int32
}
func Store(ctx context.Context, dbQueries *repository.Queries, res *ResultStore) (uuid.UUID, error) {
dbId, err := dbQueries.SetResult(ctx, &repository.SetResultParams{
Queryid: database.MustToDBUUID(res.QueryID),
Documentid: database.MustToDBUUID(res.DocumentID),
Value: res.Value,
Cleanversion: res.CleanVersion,
Textversion: res.TextVersion,
Queryversion: res.QueryVersion,
})
if err != nil {
return uuid.Nil, err
func New(db *database.Connection) *Service {
return &Service{
db,
}
id := database.MustToUUID(dbId)
return id, nil
}
+25
View File
@@ -0,0 +1,25 @@
package result_test
import (
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/query/result"
"testing"
"github.com/pashagolub/pgxmock/v3"
"github.com/stretchr/testify/assert"
)
func TestService(t *testing.T) {
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
svc := result.New(db)
assert.NotNil(t, svc)
}
+45
View File
@@ -0,0 +1,45 @@
package result
import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
resultprocessor "queryorchestration/internal/query/result/processor"
"github.com/google/uuid"
)
type Set struct {
DocumentID uuid.UUID
CleanVersion int32
TextVersion int32
Query *resultprocessor.Query
}
func (s *Service) Set(ctx context.Context, params *Set) (uuid.UUID, error) {
value, err := s.Process(ctx, &Process{
DocumentID: params.DocumentID,
MinCleanVersion: params.CleanVersion,
MinTextVersion: params.TextVersion,
Query: params.Query,
})
if err != nil {
return uuid.Nil, err
}
dbId, err := s.db.Queries.SetResult(ctx, &repository.SetResultParams{
Queryid: database.MustToDBUUID(params.Query.ID),
Documentid: database.MustToDBUUID(params.DocumentID),
Value: value.GetStoreValue(),
Cleanversion: params.CleanVersion,
Textversion: params.TextVersion,
Queryversion: params.Query.Version,
})
if err != nil {
return uuid.Nil, err
}
id := database.MustToUUID(dbId)
return id, nil
}
+67
View File
@@ -0,0 +1,67 @@
package result
import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
resultprocessor "queryorchestration/internal/query/result/processor"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/pashagolub/pgxmock/v3"
"github.com/stretchr/testify/assert"
)
func TestSet(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
svc := Service{
db: db,
}
rid := uuid.New()
cfg := "{\"path\":\"examplekey\"}"
params := Set{
DocumentID: uuid.New(),
CleanVersion: 1,
TextVersion: 3,
Query: &resultprocessor.Query{
ID: uuid.New(),
Version: 2,
Config: &cfg,
RequiredQueryIDs: &[]uuid.UUID{
uuid.New(),
},
},
}
pool.ExpectQuery("name: ListQueryRequirementValues :many").WithArgs(database.MustToDBUUID(params.Query.ID), params.Query.Version, database.MustToDBUUID(params.DocumentID), params.CleanVersion, params.TextVersion).
WillReturnRows(
pgxmock.NewRows([]string{"queryId", "value", "type"}).
AddRow(database.MustToDBUUID((*params.Query.RequiredQueryIDs)[0]), "{\"examplekey\":\"example_value\"}", repository.QuerytypeContextFull),
)
pool.ExpectQuery("name: GetQueryConfig :one").WithArgs(database.MustToDBUUID(params.Query.ID), params.Query.Version).WillReturnRows(
pgxmock.NewRows([]string{"id", "config"}).
AddRow(pgtype.UUID{}, []byte(cfg)),
)
pool.ExpectQuery("name: SetResult :one").WithArgs(database.MustToDBUUID(params.Query.ID), database.MustToDBUUID(params.DocumentID), pgxmock.AnyArg(), params.CleanVersion, params.TextVersion, params.Query.Version).
WillReturnRows(
pgxmock.NewRows([]string{"id"}).
AddRow(database.MustToDBUUID(rid)),
)
id, err := svc.Set(ctx, &params)
assert.Nil(t, err)
assert.Equal(t, rid, id)
}
-50
View File
@@ -1,50 +0,0 @@
package result_test
import (
"context"
"errors"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/query/result"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/pashagolub/pgxmock/v3"
"github.com/stretchr/testify/assert"
)
func TestStore(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
resultStore := result.ResultStore{
QueryID: uuid.New(),
DocumentID: uuid.New(),
Value: "val",
CleanVersion: int32(1),
TextVersion: int32(1),
QueryVersion: int32(1),
}
pool.ExpectQuery("name: SetResult :one").WithArgs(database.MustToDBUUID(resultStore.QueryID), database.MustToDBUUID(resultStore.DocumentID), resultStore.Value, resultStore.CleanVersion, resultStore.TextVersion, resultStore.QueryVersion).
WillReturnRows(
pgxmock.NewRows([]string{"id"}).AddRow(pgtype.UUID{}),
)
id, err := result.Store(ctx, queries, &resultStore)
assert.Nil(t, err)
assert.NotNil(t, id)
dbErr := "database failing"
pool.ExpectQuery("name: SetResult :one").WithArgs(database.MustToDBUUID(resultStore.QueryID), database.MustToDBUUID(resultStore.DocumentID), resultStore.Value, resultStore.CleanVersion, resultStore.TextVersion, resultStore.QueryVersion).
WillReturnError(errors.New(dbErr))
id, err = result.Store(ctx, queries, &resultStore)
assert.EqualError(t, err, dbErr)
assert.Equal(t, uuid.Nil, id)
}
+18
View File
@@ -0,0 +1,18 @@
package result
import (
"context"
"queryorchestration/internal/database"
resultprocessor "queryorchestration/internal/query/result/processor"
"github.com/google/uuid"
)
func (s *Service) ListUnsyncedQueriesByDocId(ctx context.Context, id uuid.UUID) ([]*resultprocessor.Query, error) {
qs, err := s.db.Queries.ListUnsyncedQueriesByDocId(ctx, database.MustToDBUUID(id))
if err != nil {
return nil, err
}
return resultprocessor.ParseFullQueryArray(qs)
}
+49
View File
@@ -0,0 +1,49 @@
package result_test
import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/query/result"
resultprocessor "queryorchestration/internal/query/result/processor"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/pashagolub/pgxmock/v3"
"github.com/stretchr/testify/assert"
)
func TestListUnsyncedQueriesByDocId(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
svc := result.New(db)
documentId := uuid.New()
actualQs := []*resultprocessor.Query{
{
ID: uuid.New(),
Type: resultprocessor.TypeJsonExtractor,
Version: 2,
},
}
pool.ExpectQuery("name: ListUnsyncedQueriesByDocId :many").WithArgs(database.MustToDBUUID(documentId)).
WillReturnRows(
pgxmock.NewRows([]string{"id", "type", "activeVersion", "latestVersion", "config", "requiredIds"}).
AddRow(database.MustToDBUUID(actualQs[0].ID), repository.QuerytypeJsonExtractor, actualQs[0].Version, actualQs[0].Version, nil, []pgtype.UUID{}),
)
val, err := svc.ListUnsyncedQueriesByDocId(ctx, documentId)
assert.Nil(t, err)
assert.ElementsMatch(t, actualQs, val)
}
+27 -3
View File
@@ -1,13 +1,37 @@
package query
import "queryorchestration/internal/database"
import (
"queryorchestration/internal/database"
"queryorchestration/internal/document"
documenttext "queryorchestration/internal/document/text"
"queryorchestration/internal/job/collector"
"queryorchestration/internal/query/result"
"github.com/google/uuid"
)
type Services struct {
Text *documenttext.Service
Result *result.Service
Collector *collector.Service
Document *document.Service
}
type Service struct {
db *database.Connection
db *database.Connection
svc *Services
}
func New(db *database.Connection) *Service {
func New(db *database.Connection, svc *Services) *Service {
return &Service{
db,
svc,
}
}
type Document struct {
ID uuid.UUID `json:"id" validate:"required,uuid"`
JobID uuid.UUID `json:"jobId" validate:"required,uuid"`
CleanVersion int32 `json:"cleanVersion" validate:"required,gt=0"`
TextVersion int32 `json:"textVersion" validate:"required,gt=0"`
}
+1 -1
View File
@@ -20,6 +20,6 @@ func TestService(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := query.New(db)
svc := query.New(db, &query.Services{})
assert.NotNil(t, svc)
}
+163
View File
@@ -0,0 +1,163 @@
package query
import (
"context"
"errors"
documenttext "queryorchestration/internal/document/text"
"queryorchestration/internal/query/result"
resultprocessor "queryorchestration/internal/query/result/processor"
"sync"
"github.com/google/uuid"
)
func (s *Service) Sync(ctx context.Context, doc *Document) error {
err := s.svc.Text.IsExtracted(&documenttext.IsExtractedParams{
DocumentID: doc.ID,
MinCleanVersion: doc.CleanVersion,
MinTextVersion: doc.TextVersion,
})
if err != nil {
return err
}
unsyncedQueries, err := s.svc.Result.ListUnsyncedQueriesByDocId(ctx, doc.ID)
if err != nil {
return err
}
batchedQueries := s.batchQueries(unsyncedQueries)
for _, queries := range batchedQueries {
err := s.processBatch(ctx, doc, queries)
if err != nil {
return err
}
}
return nil
}
func (s *Service) batchQueries(queries []*resultprocessor.Query) [][]*resultprocessor.Query {
n := len(queries)
if n == 0 {
return nil
}
idToIndex := make(map[uuid.UUID]int, n)
for i, q := range queries {
idToIndex[q.ID] = i
}
result := make([][]*resultprocessor.Query, 0, n)
assigned := make([]bool, n)
deps := make([][]int, n)
remaining := n
for i, q := range queries {
toAppend := false
if q.RequiredQueryIDs == nil || len(*q.RequiredQueryIDs) == 0 {
toAppend = true
} else {
deps[i] = make([]int, 0, len(*q.RequiredQueryIDs))
for _, reqID := range *q.RequiredQueryIDs {
if idx, exists := idToIndex[reqID]; exists {
deps[i] = append(deps[i], idx)
}
}
toAppend = len(deps[i]) == 0
}
if toAppend {
if len(result) == 0 {
result = [][]*resultprocessor.Query{{q}}
} else {
result[0] = append(result[0], q)
}
assigned[idToIndex[q.ID]] = true
remaining--
}
}
for remaining > 0 {
currentLayer := make([]*resultprocessor.Query, 0, remaining)
for i, q := range queries {
if assigned[i] {
continue
}
allSatisfied := true
for _, depIdx := range deps[i] {
if !assigned[depIdx] {
allSatisfied = false
break
}
}
if allSatisfied {
currentLayer = append(currentLayer, q)
}
}
for _, v := range currentLayer {
assigned[idToIndex[v.ID]] = true
remaining--
}
result = append(result, currentLayer)
}
return result
}
func (s *Service) processBatch(ctx context.Context, doc *Document, queries []*resultprocessor.Query) error {
if doc == nil {
return errors.New("document required")
}
errChan := make(chan error, len(queries))
var wg sync.WaitGroup
sem := make(chan struct{}, 10)
for _, query := range queries {
wg.Add(1)
go func(q *resultprocessor.Query) {
defer wg.Done()
sem <- struct{}{}
defer func() {
<-sem
}()
select {
case <-ctx.Done():
errChan <- ctx.Err()
return
default:
}
_, err := s.svc.Result.Set(ctx, &result.Set{
DocumentID: doc.ID,
CleanVersion: doc.CleanVersion,
TextVersion: doc.TextVersion,
Query: query,
})
if err != nil {
errChan <- err
}
}(query)
}
wg.Wait()
close(errChan)
for err := range errChan {
if err != nil {
return err
}
}
return nil
}
+307
View File
@@ -0,0 +1,307 @@
package query
import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/job/collector"
"queryorchestration/internal/query/result"
resultprocessor "queryorchestration/internal/query/result/processor"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/pashagolub/pgxmock/v3"
"github.com/stretchr/testify/assert"
)
func TestBatchQueries(t *testing.T) {
svc := Service{}
in := []*resultprocessor.Query{}
out := svc.batchQueries(in)
assert.ElementsMatch(t, [][]*resultprocessor.Query{}, out)
in = []*resultprocessor.Query{
{
ID: uuid.New(),
},
}
out = svc.batchQueries(in)
assert.ElementsMatch(t, [][]*resultprocessor.Query{
{
in[0],
},
}, out)
in = []*resultprocessor.Query{
{
ID: uuid.New(),
RequiredQueryIDs: &[]uuid.UUID{uuid.New()},
},
}
out = svc.batchQueries(in)
assert.ElementsMatch(t, [][]*resultprocessor.Query{
{
in[0],
},
}, out)
in = []*resultprocessor.Query{
{
ID: uuid.New(),
},
{
ID: uuid.New(),
},
}
out = svc.batchQueries(in)
assert.ElementsMatch(t, [][]*resultprocessor.Query{
{
in[0],
in[1],
},
}, out)
idone := uuid.New()
in = []*resultprocessor.Query{
{
ID: idone,
},
{
ID: uuid.New(),
RequiredQueryIDs: &[]uuid.UUID{
idone,
},
},
}
out = svc.batchQueries(in)
assert.ElementsMatch(t, [][]*resultprocessor.Query{
{
in[0],
},
{
in[1],
},
}, out)
in = []*resultprocessor.Query{
{
ID: uuid.New(),
RequiredQueryIDs: &[]uuid.UUID{
idone,
},
},
{
ID: idone,
},
}
out = svc.batchQueries(in)
assert.ElementsMatch(t, [][]*resultprocessor.Query{
{
in[1],
},
{
in[0],
},
}, out)
in = []*resultprocessor.Query{
{
ID: idone,
},
{
ID: uuid.New(),
RequiredQueryIDs: &[]uuid.UUID{
idone,
},
},
{
ID: uuid.New(),
RequiredQueryIDs: &[]uuid.UUID{
idone,
},
},
{
ID: uuid.New(),
},
}
out = svc.batchQueries(in)
assert.ElementsMatch(t, [][]*resultprocessor.Query{
{
in[0],
in[3],
},
{
in[1],
in[2],
},
}, out)
idtwo := uuid.New()
idthree := uuid.New()
in = []*resultprocessor.Query{
{
ID: idone,
},
{
ID: idtwo,
RequiredQueryIDs: &[]uuid.UUID{
idone,
},
},
{
ID: idthree,
RequiredQueryIDs: &[]uuid.UUID{
idtwo,
},
},
{
ID: uuid.New(),
RequiredQueryIDs: &[]uuid.UUID{
idthree,
},
},
}
out = svc.batchQueries(in)
assert.ElementsMatch(t, [][]*resultprocessor.Query{
{
in[0],
},
{
in[1],
},
{
in[2],
},
{
in[3],
},
}, out)
}
func TestProcessBatch(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
svc := Service{
svc: &Services{
Result: result.New(db),
},
}
assert.Error(t, svc.processBatch(ctx, nil, nil))
doc := &Document{
ID: uuid.New(),
CleanVersion: 1,
TextVersion: 1,
}
assert.Nil(t, svc.processBatch(ctx, doc, nil))
qs := []*resultprocessor.Query{}
assert.Nil(t, svc.processBatch(ctx, doc, qs))
coll := &collector.Collector{
ID: uuid.New(),
MinCleanVersion: 1,
MinTextVersion: 1,
}
qs = []*resultprocessor.Query{
{
ID: uuid.New(),
Type: resultprocessor.TypeContextFull,
Version: 1,
},
}
pool.ExpectQuery("name: SetResult :one").WithArgs(database.MustToDBUUID(qs[0].ID), database.MustToDBUUID(doc.ID), pgxmock.AnyArg(), coll.MinCleanVersion, coll.MinTextVersion, qs[0].Version).
WillReturnRows(
pgxmock.NewRows([]string{"id"}).
AddRow(pgtype.UUID{}),
)
pool.ExpectQuery("name: GetCollectorByJobID :one").WithArgs(database.MustToDBUUID(doc.JobID)).
WillReturnRows(
pgxmock.NewRows([]string{"id", "jobId", "minCleanVersion", "minTextVersion", "activeVersion", "latestVersion", "fields"}).
AddRow(database.MustToDBUUID(coll.ID), database.MustToDBUUID(doc.JobID), coll.MinCleanVersion, coll.MinTextVersion, int32(1), int32(2), []byte("")),
)
pool.ExpectQuery("name: ListCollectorQueries :many").WithArgs(database.MustToDBUUID(coll.ID)).
WillReturnRows(
pgxmock.NewRows([]string{"collectorId", "queryId", "type", "queryVersion", "requiredIds"}).
AddRow(database.MustToDBUUID(coll.ID), database.MustToDBUUID(qs[0].ID), repository.QuerytypeContextFull, qs[0].Version, []pgtype.UUID{}),
)
assert.Nil(t, svc.processBatch(ctx, doc, qs))
}
func TestSync(t *testing.T) {
ctx := context.Background()
pool, err := pgxmock.NewPool()
if err != nil {
t.Fatalf("failed to open pgxmock database: %v", err)
}
queries := repository.New(pool)
db := &database.Connection{
Queries: queries,
Pool: pool,
}
svc := Service{
svc: &Services{
Result: result.New(db),
},
}
assert.Error(t, svc.processBatch(ctx, nil, nil))
doc := &Document{
ID: uuid.New(),
CleanVersion: 1,
TextVersion: 1,
}
assert.Nil(t, svc.processBatch(ctx, doc, nil))
qs := []*resultprocessor.Query{}
assert.Nil(t, svc.processBatch(ctx, doc, qs))
coll := &collector.Collector{
ID: uuid.New(),
MinCleanVersion: 1,
MinTextVersion: 1,
}
qs = []*resultprocessor.Query{
{
ID: uuid.New(),
Type: resultprocessor.TypeContextFull,
Version: 1,
},
}
pool.ExpectQuery("name: ListUnsyncedQueriesByDocId :many").WithArgs(database.MustToDBUUID(doc.ID)).
WillReturnRows(
pgxmock.NewRows([]string{"id", "type", "activeVersion", "latestVersion", "config", "requiredIds"}).
AddRow(database.MustToDBUUID(qs[0].ID), repository.QuerytypeContextFull, qs[0].Version, qs[0].Version, nil, []pgtype.UUID{}),
)
pool.ExpectQuery("name: SetResult :one").WithArgs(database.MustToDBUUID(qs[0].ID), database.MustToDBUUID(doc.ID), pgxmock.AnyArg(), coll.MinCleanVersion, coll.MinTextVersion, qs[0].Version).
WillReturnRows(
pgxmock.NewRows([]string{"id"}).
AddRow(pgtype.UUID{}),
)
pool.ExpectQuery("name: GetCollectorByJobID :one").WithArgs(database.MustToDBUUID(doc.JobID)).
WillReturnRows(
pgxmock.NewRows([]string{"id", "jobId", "minCleanVersion", "minTextVersion", "activeVersion", "latestVersion", "fields"}).
AddRow(database.MustToDBUUID(coll.ID), database.MustToDBUUID(doc.JobID), coll.MinCleanVersion, coll.MinTextVersion, int32(1), int32(2), []byte("")),
)
pool.ExpectQuery("name: ListCollectorQueries :many").WithArgs(database.MustToDBUUID(coll.ID)).
WillReturnRows(
pgxmock.NewRows([]string{"collectorId", "queryId", "type", "queryVersion", "requiredIds"}).
AddRow(database.MustToDBUUID(coll.ID), database.MustToDBUUID(qs[0].ID), repository.QuerytypeContextFull, qs[0].Version, []pgtype.UUID{}),
)
assert.Nil(t, svc.Sync(ctx, doc))
}
+44 -4
View File
@@ -2,6 +2,8 @@ package query
import (
"context"
"queryorchestration/internal/query/result"
resultprocessor "queryorchestration/internal/query/result/processor"
"github.com/google/uuid"
)
@@ -13,9 +15,47 @@ type Test struct {
}
func (s *Service) Test(ctx context.Context, filters Test) (string, error) {
// TODO
// Sync doc - documentID
// Run test - queryID, queryVersion
doc, err := s.svc.Document.Get(ctx, filters.DocumentID)
if err != nil {
return "", err
}
return "", nil
col, err := s.svc.Collector.GetByJobID(ctx, doc.JobID)
if err != nil {
return "", err
}
res, err := s.svc.Result.GetValueWithVersion(ctx, &result.GetValueWithVersionParams{
QueryID: filters.QueryID,
DocumentID: filters.DocumentID,
QueryVersion: filters.QueryVersion,
MinCleanVersion: col.MinCleanVersion,
MinTextVersion: col.MinTextVersion,
})
if err == nil {
return res.GetValue(ctx)
}
q, err := s.GetWithVersion(ctx, filters.QueryID, filters.QueryVersion)
if err != nil {
return "", err
}
value, err := s.svc.Result.Process(ctx, &result.Process{
DocumentID: filters.DocumentID,
MinCleanVersion: col.MinCleanVersion,
MinTextVersion: col.MinTextVersion,
Query: &resultprocessor.Query{
ID: q.ID,
Type: q.Type,
Version: filters.QueryVersion,
RequiredQueryIDs: q.RequiredQueryIDs,
Config: q.Config,
},
})
if err != nil {
return "", err
}
return value.GetValue(ctx)
}
+56 -3
View File
@@ -4,10 +4,16 @@ import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/document"
documentclean "queryorchestration/internal/document/clean"
documenttext "queryorchestration/internal/document/text"
"queryorchestration/internal/job/collector"
"queryorchestration/internal/query"
"queryorchestration/internal/query/result"
"testing"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/pashagolub/pgxmock/v3"
"github.com/stretchr/testify/assert"
)
@@ -24,15 +30,62 @@ func TestTest(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := query.New(db)
text := documenttext.New()
clean := documentclean.New()
col := collector.New(db, &collector.Services{
Text: text,
Clean: clean,
})
docsvc := document.New(db)
svc := query.New(db, &query.Services{
Text: text,
Document: docsvc,
Collector: col,
Result: result.New(db),
})
coll := collector.Collector{
ID: uuid.New(),
JobID: uuid.New(),
}
doc := document.Document{
ID: uuid.New(),
JobID: coll.JobID,
Hash: "example_hash",
Location: "example_location",
}
params := &query.Test{
QueryID: uuid.New(),
DocumentID: uuid.New(),
DocumentID: doc.ID,
QueryVersion: int32(1),
}
reqID := database.MustToDBUUID(uuid.New())
pool.ExpectQuery("name: GetDocument :one").WithArgs(database.MustToDBUUID(doc.ID)).
WillReturnRows(
pgxmock.NewRows([]string{"id", "jobId", "hash", "location"}).
AddRow(database.MustToDBUUID(doc.ID), database.MustToDBUUID(doc.JobID), doc.Hash, doc.Location),
)
pool.ExpectQuery("name: GetCollectorByJobID :one").WithArgs(database.MustToDBUUID(doc.JobID)).
WillReturnRows(
pgxmock.NewRows([]string{"id", "jobId", "minCleanVersion", "minTextVersion", "activeVersion", "latestVersion", "fields"}).
AddRow(database.MustToDBUUID(coll.ID), database.MustToDBUUID(doc.JobID), coll.MinCleanVersion, coll.MinTextVersion, int32(1), int32(2), []byte("")),
)
pool.ExpectQuery("name: GetQueryWithVersion :one").WithArgs(database.MustToDBUUID(params.QueryID), params.QueryVersion).WillReturnRows(
pgxmock.NewRows([]string{"id", "type", "activeVersion", "latestVersion", "config", "requiredIds"}).
AddRow(database.MustToDBUUID(params.QueryID), repository.QuerytypeJsonExtractor, int32(1), params.QueryVersion+1, []byte("{\"path\":\"oldkey\"}"), []pgtype.UUID{reqID}),
)
pool.ExpectQuery("name: ListQueryRequirementValues :many").WithArgs(database.MustToDBUUID(params.QueryID), params.QueryVersion, database.MustToDBUUID(params.DocumentID), coll.MinCleanVersion, coll.MinTextVersion).
WillReturnRows(
pgxmock.NewRows([]string{"queryId", "value", "type"}).
AddRow(reqID, "{\"mykey\":\"example_value\",\"oldkey\":\"old_value\"}", repository.QuerytypeContextFull),
)
pool.ExpectQuery("name: GetQueryConfig :one").WithArgs(database.MustToDBUUID(params.QueryID), params.QueryVersion).WillReturnRows(
pgxmock.NewRows([]string{"id", "config"}).
AddRow(pgtype.UUID{}, []byte("{\"path\":\"oldkey\"}")),
)
result, err := svc.Test(ctx, *params)
assert.Nil(t, err)
assert.Empty(t, result)
assert.Equal(t, "old_value", result)
}
+2 -2
View File
@@ -3,7 +3,7 @@ package contextfull
import (
"context"
"queryorchestration/internal/database"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
)
type Creator struct {
@@ -14,7 +14,7 @@ func NewCreator(db *database.Connection) Creator {
return Creator{db}
}
func (s Creator) Validate(ctx context.Context, entity *queryprocessor.Create) error {
func (s Creator) Validate(ctx context.Context, entity *resultprocessor.Create) error {
// TODO
// Type, RequiredQueryIDs, Config
return nil
@@ -4,7 +4,7 @@ import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
contextfull "queryorchestration/internal/query/types/contextFull"
"testing"
@@ -28,8 +28,8 @@ func TestCreatorValidate(t *testing.T) {
svc := contextfull.NewCreator(db)
assert.NotNil(t, svc)
entity := &queryprocessor.Create{
Type: queryprocessor.TypeContextFull,
entity := &resultprocessor.Create{
Type: resultprocessor.TypeContextFull,
}
err = svc.Validate(ctx, entity)
@@ -2,8 +2,7 @@ package contextfull_test
import (
"context"
queryprocessor "queryorchestration/internal/query/processor"
"queryorchestration/internal/query/result"
resultprocessor "queryorchestration/internal/query/result/processor"
contextfull "queryorchestration/internal/query/types/contextFull"
"testing"
@@ -16,19 +15,19 @@ func TestContextFull(t *testing.T) {
extractor := contextfull.NewExtractor()
query := &queryprocessor.Query{
query := &resultprocessor.Query{
ID: uuid.New(),
Type: queryprocessor.TypeJsonExtractor,
Type: resultprocessor.TypeJsonExtractor,
Version: int32(1),
}
values := []result.Value{}
values := []resultprocessor.Value{}
value, err := extractor.Process(ctx, query, &values)
assert.Nil(t, err)
assert.Equal(t, "", value)
values = []result.Value{
values = []resultprocessor.Value{
contextfull.NewResult("example_result"),
}
@@ -16,3 +16,7 @@ func (r Result) GetValue(ctx context.Context) (string, error) {
// TODO - get value from s3
return r.value, nil
}
func (r Result) GetStoreValue() string {
return r.value
}
+2 -3
View File
@@ -3,8 +3,7 @@ package contextfull
import (
"context"
"errors"
queryprocessor "queryorchestration/internal/query/processor"
"queryorchestration/internal/query/result"
resultprocessor "queryorchestration/internal/query/result/processor"
)
type Extractor struct {
@@ -14,7 +13,7 @@ func NewExtractor() Extractor {
return Extractor{}
}
func (e Extractor) Process(ctx context.Context, query *queryprocessor.Query, values *[]result.Value) (string, error) {
func (e Extractor) Process(ctx context.Context, query *resultprocessor.Query, values *[]resultprocessor.Value) (string, error) {
if values != nil && len(*values) > 0 {
return "", errors.New("no requirements expected")
}
+2 -2
View File
@@ -3,7 +3,7 @@ package contextfull
import (
"context"
"queryorchestration/internal/database"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
)
type Updator struct {
@@ -14,7 +14,7 @@ func NewUpdator(db *database.Connection) Updator {
return Updator{db}
}
func (s Updator) Validate(ctx context.Context, current *queryprocessor.Query, entity *queryprocessor.Update) error {
func (s Updator) Validate(ctx context.Context, current *resultprocessor.Query, entity *resultprocessor.Update) error {
// TODO
// Type, RequiredQueryIDs, Config
return nil
@@ -4,7 +4,7 @@ import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
contextfull "queryorchestration/internal/query/types/contextFull"
"testing"
@@ -29,13 +29,13 @@ func TestUpdatorValidate(t *testing.T) {
svc := contextfull.NewUpdator(db)
assert.NotNil(t, svc)
current := &queryprocessor.Query{
current := &resultprocessor.Query{
ID: uuid.New(),
Type: queryprocessor.TypeContextFull,
Type: resultprocessor.TypeContextFull,
Version: int32(1),
}
entity := &queryprocessor.Update{
entity := &resultprocessor.Update{
ID: current.ID,
}
@@ -3,7 +3,7 @@ package jsonextractor
import (
"context"
"queryorchestration/internal/database"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
)
type Creator struct {
@@ -14,7 +14,7 @@ func NewCreator(db *database.Connection) Creator {
return Creator{db}
}
func (s Creator) Validate(ctx context.Context, entity *queryprocessor.Create) error {
func (s Creator) Validate(ctx context.Context, entity *resultprocessor.Create) error {
// TODO
return nil
}
@@ -4,7 +4,7 @@ import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
jsonextractor "queryorchestration/internal/query/types/jsonExtractor"
"testing"
@@ -28,8 +28,8 @@ func TestCreatorValidate(t *testing.T) {
svc := jsonextractor.NewCreator(db)
assert.NotNil(t, svc)
entity := &queryprocessor.Create{
Type: queryprocessor.TypeJsonExtractor,
entity := &resultprocessor.Create{
Type: resultprocessor.TypeJsonExtractor,
}
err = svc.Validate(ctx, entity)
@@ -5,8 +5,7 @@ import (
"fmt"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
"queryorchestration/internal/query/result"
resultprocessor "queryorchestration/internal/query/result/processor"
contextfull "queryorchestration/internal/query/types/contextFull"
jsonextractor "queryorchestration/internal/query/types/jsonExtractor"
"testing"
@@ -32,15 +31,15 @@ func TestJSONProcess(t *testing.T) {
extractor := jsonextractor.NewExtractor(db)
query := &queryprocessor.Query{
query := &resultprocessor.Query{
ID: uuid.New(),
Type: queryprocessor.TypeJsonExtractor,
Type: resultprocessor.TypeJsonExtractor,
Version: int32(1),
}
entryValue := "value"
jsonString := fmt.Sprintf("{\"key\": \"%s\"}", entryValue)
values := []result.Value{
values := []resultprocessor.Value{
contextfull.NewResult(jsonString),
}
@@ -58,7 +57,7 @@ func TestJSONProcess(t *testing.T) {
entryValue = ""
jsonString = fmt.Sprintf("{\"key\": \"%s\"}", entryValue)
values = []result.Value{
values = []resultprocessor.Value{
contextfull.NewResult(jsonString),
}
pool.ExpectQuery("name: GetQueryConfig :one").WithArgs(database.MustToDBUUID(query.ID), query.Version).
@@ -73,7 +72,7 @@ func TestJSONProcess(t *testing.T) {
entryValue = "1"
jsonString = fmt.Sprintf("{\"key\": %s", entryValue)
values = []result.Value{
values = []resultprocessor.Value{
contextfull.NewResult(jsonString),
}
pool.ExpectQuery("name: GetQueryConfig :one").WithArgs(database.MustToDBUUID(query.ID), query.Version).
@@ -102,15 +101,15 @@ func TestJSONProcessJSON(t *testing.T) {
extractor := jsonextractor.NewExtractor(db)
query := &queryprocessor.Query{
query := &resultprocessor.Query{
ID: uuid.New(),
Type: queryprocessor.TypeJsonExtractor,
Type: resultprocessor.TypeJsonExtractor,
Version: int32(1),
}
entryValue := "value"
jsonString := fmt.Sprintf("{\"key\": \"%s\"}", entryValue)
values := []result.Value{
values := []resultprocessor.Value{
contextfull.NewResult(jsonString),
}
@@ -187,18 +186,18 @@ func TestJSONProcessResults(t *testing.T) {
extractor := jsonextractor.NewExtractor(db)
query := &queryprocessor.Query{
query := &resultprocessor.Query{
ID: uuid.New(),
Type: queryprocessor.TypeJsonExtractor,
Type: resultprocessor.TypeJsonExtractor,
Version: int32(1),
}
results := []result.Value{}
results := []resultprocessor.Value{}
value, err := extractor.Process(ctx, query, &results)
assert.EqualError(t, err, "JSON Extraction requires 1 result")
assert.Empty(t, value)
results = []result.Value{
results = []resultprocessor.Value{
contextfull.NewResult(""),
contextfull.NewResult(""),
}
@@ -206,7 +205,7 @@ func TestJSONProcessResults(t *testing.T) {
assert.EqualError(t, err, "JSON Extraction requires 1 result")
assert.Empty(t, value)
results = []result.Value{
results = []resultprocessor.Value{
contextfull.NewResult(""),
contextfull.NewResult(""),
contextfull.NewResult(""),
@@ -15,3 +15,7 @@ func NewResult(value string) Result {
func (r Result) GetValue(ctx context.Context) (string, error) {
return r.value, nil
}
func (r Result) GetStoreValue() string {
return r.value
}
@@ -6,8 +6,7 @@ import (
"fmt"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
"queryorchestration/internal/query/result"
resultprocessor "queryorchestration/internal/query/result/processor"
"github.com/tidwall/gjson"
)
@@ -24,7 +23,7 @@ func NewExtractor(db *database.Connection) Extractor {
return Extractor{db}
}
func (e Extractor) Process(ctx context.Context, query *queryprocessor.Query, values *[]result.Value) (string, error) {
func (e Extractor) Process(ctx context.Context, query *resultprocessor.Query, values *[]resultprocessor.Value) (string, error) {
if values == nil || len(*values) != 1 {
return "", fmt.Errorf("JSON Extraction requires 1 result")
}
@@ -3,7 +3,7 @@ package jsonextractor
import (
"context"
"queryorchestration/internal/database"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
)
type Updator struct {
@@ -14,7 +14,7 @@ func NewUpdator(db *database.Connection) Updator {
return Updator{db}
}
func (s Updator) Validate(ctx context.Context, current *queryprocessor.Query, entity *queryprocessor.Update) error {
func (s Updator) Validate(ctx context.Context, current *resultprocessor.Query, entity *resultprocessor.Update) error {
// TODO
return nil
}
@@ -4,7 +4,7 @@ import (
"context"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
jsonextractor "queryorchestration/internal/query/types/jsonExtractor"
"testing"
@@ -29,13 +29,13 @@ func TestUpdatorValidate(t *testing.T) {
svc := jsonextractor.NewUpdator(db)
assert.NotNil(t, svc)
current := &queryprocessor.Query{
current := &resultprocessor.Query{
ID: uuid.New(),
Type: queryprocessor.TypeJsonExtractor,
Type: resultprocessor.TypeJsonExtractor,
Version: int32(1),
}
entity := &queryprocessor.Update{
entity := &resultprocessor.Update{
ID: current.ID,
}
+9 -9
View File
@@ -6,14 +6,14 @@ import (
"fmt"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
contextfull "queryorchestration/internal/query/types/contextFull"
jsonextractor "queryorchestration/internal/query/types/jsonExtractor"
"github.com/google/uuid"
)
func (s *Service) Update(ctx context.Context, entity *queryprocessor.Update) error {
func (s *Service) Update(ctx context.Context, entity *resultprocessor.Update) error {
current, err := s.Get(ctx, entity.ID)
if err != nil {
return err
@@ -32,7 +32,7 @@ func (s *Service) Update(ctx context.Context, entity *queryprocessor.Update) err
return nil
}
func (s *Service) normalizeUpdate(ctx context.Context, current *Query, entity *queryprocessor.Update) error {
func (s *Service) normalizeUpdate(ctx context.Context, current *Query, entity *resultprocessor.Update) error {
err := s.normalizeActiveVersion(current, entity)
if err != nil {
return err
@@ -79,7 +79,7 @@ func (s *Service) normalizeUpdate(ctx context.Context, current *Query, entity *q
return nil
}
func (s *Service) submitUpdate(ctx context.Context, current *Query, entity *queryprocessor.Update) error {
func (s *Service) submitUpdate(ctx context.Context, current *Query, entity *resultprocessor.Update) error {
tx, err := s.db.Pool.Begin(ctx)
if err != nil {
return err
@@ -182,19 +182,19 @@ func getSetDifference(setA *[]uuid.UUID, setB *[]uuid.UUID) []uuid.UUID {
return diff
}
func (s *Service) getUpdator(qType queryprocessor.Type) (queryprocessor.Updator, error) {
func (s *Service) getUpdator(qType resultprocessor.Type) (resultprocessor.Updator, error) {
switch qType {
case queryprocessor.TypeJsonExtractor:
case resultprocessor.TypeJsonExtractor:
return jsonextractor.NewUpdator(s.db), nil
case queryprocessor.TypeContextFull:
case resultprocessor.TypeContextFull:
return contextfull.NewUpdator(s.db), nil
default:
return nil, fmt.Errorf("attempting to process invalid query type")
}
}
func ParseQuery(q *Query) *queryprocessor.Query {
return &queryprocessor.Query{
func ParseQuery(q *Query) *resultprocessor.Query {
return &resultprocessor.Query{
ID: q.ID,
Type: q.Type,
Version: q.ActiveVersion,
+3 -3
View File
@@ -5,7 +5,7 @@ import (
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
"queryorchestration/internal/query"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
"testing"
"github.com/google/uuid"
@@ -26,7 +26,7 @@ func TestUpdate(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := query.New(db)
svc := query.New(db, &query.Services{})
config := "{\"path\":\"example_path\"}"
existing := query.Query{
@@ -34,7 +34,7 @@ func TestUpdate(t *testing.T) {
ActiveVersion: int32(1),
LatestVersion: int32(1),
}
update := &queryprocessor.Update{
update := &resultprocessor.Update{
ID: existing.ID,
}
+18 -18
View File
@@ -5,7 +5,7 @@ import (
"errors"
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
resultprocessor "queryorchestration/internal/query/result/processor"
"testing"
"github.com/google/uuid"
@@ -24,19 +24,19 @@ func TestGetUpdator(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := New(db)
svc := New(db, &Services{})
queryType := queryprocessor.Type(queryprocessor.TypeContextFull)
queryType := resultprocessor.Type(resultprocessor.TypeContextFull)
updator, err := svc.getUpdator(queryType)
assert.Nil(t, err)
assert.NotNil(t, updator)
queryType = queryprocessor.Type(queryprocessor.TypeJsonExtractor)
queryType = resultprocessor.Type(resultprocessor.TypeJsonExtractor)
updator, err = svc.getUpdator(queryType)
assert.Nil(t, err)
assert.NotNil(t, updator)
queryType = queryprocessor.Type(-1)
queryType = resultprocessor.Type(-1)
_, err = svc.getUpdator(queryType)
assert.NotNil(t, err)
}
@@ -53,7 +53,7 @@ func TestSubmitUpdate(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := New(db)
svc := New(db, &Services{})
config := "{\"path\":\"example_path\"}"
q := Query{
@@ -66,7 +66,7 @@ func TestSubmitUpdate(t *testing.T) {
LatestVersion: int32(2),
}
aV := int32(10)
update := &queryprocessor.Update{
update := &resultprocessor.Update{
ID: q.ID,
RequiredQueryIDs: &[]uuid.UUID{
uuid.New(),
@@ -104,7 +104,7 @@ func TestSubmitUpdateRollback(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := New(db)
svc := New(db, &Services{})
q := Query{
ID: uuid.New(),
@@ -112,7 +112,7 @@ func TestSubmitUpdateRollback(t *testing.T) {
LatestVersion: int32(2),
}
aV := int32(10)
update := &queryprocessor.Update{
update := &resultprocessor.Update{
ID: q.ID,
ActiveVersion: &aV,
}
@@ -139,7 +139,7 @@ func TestSubmitUpdateRequiredQueries(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := New(db)
svc := New(db, &Services{})
config := "{\"path\":\"example_path\"}"
q := Query{
@@ -153,7 +153,7 @@ func TestSubmitUpdateRequiredQueries(t *testing.T) {
ActiveVersion: int32(1),
LatestVersion: int32(2),
}
update := &queryprocessor.Update{
update := &resultprocessor.Update{
ID: q.ID,
RequiredQueryIDs: &[]uuid.UUID{
uuid.New(),
@@ -191,7 +191,7 @@ func TestSubmitUpdateActiveVersion(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := New(db)
svc := New(db, &Services{})
q := Query{
ID: uuid.New(),
@@ -199,7 +199,7 @@ func TestSubmitUpdateActiveVersion(t *testing.T) {
LatestVersion: int32(2),
}
aV := int32(10)
update := &queryprocessor.Update{
update := &resultprocessor.Update{
ID: q.ID,
ActiveVersion: &aV,
}
@@ -238,17 +238,17 @@ func TestNormalizeUpdate(t *testing.T) {
Queries: queries,
Pool: pool,
}
svc := New(db)
svc := New(db, &Services{})
current := &Query{
ID: uuid.New(),
ActiveVersion: int32(1),
LatestVersion: int32(2),
Type: queryprocessor.TypeJsonExtractor,
Type: resultprocessor.TypeJsonExtractor,
}
cfg := "{}"
aV := int32(2)
update := &queryprocessor.Update{
update := &resultprocessor.Update{
ID: current.ID,
Config: &cfg,
ActiveVersion: &aV,
@@ -264,7 +264,7 @@ func TestNormalizeUpdate(t *testing.T) {
err = svc.normalizeUpdate(ctx, current, update)
assert.Nil(t, err)
assert.EqualExportedValues(t, queryprocessor.Update{
assert.EqualExportedValues(t, resultprocessor.Update{
ID: current.ID,
ActiveVersion: &aV,
Config: &cfg,
@@ -283,7 +283,7 @@ func TestNormalizeUpdate(t *testing.T) {
err = svc.normalizeUpdate(ctx, current, update)
assert.Error(t, err)
update = &queryprocessor.Update{
update = &resultprocessor.Update{
ID: current.ID,
}
err = svc.normalizeUpdate(ctx, current, update)