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:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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{})
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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())
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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, ¶ms)
|
||||
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, ¶ms)
|
||||
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)
|
||||
}
|
||||
+10
-10
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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, ¶ms)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, rid, id)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user