Files
query-orchestration/internal/query/update.go
T

205 lines
4.4 KiB
Go
Raw Normal View History

2025-01-03 13:41:07 +00:00
package query
import (
"context"
2025-01-23 14:56:20 +00:00
"errors"
2025-01-03 13:41:07 +00:00
"fmt"
2025-01-20 13:31:48 +00:00
"queryorchestration/internal/database"
"queryorchestration/internal/database/repository"
queryprocessor "queryorchestration/internal/query/processor"
contextfull "queryorchestration/internal/query/types/contextFull"
jsonextractor "queryorchestration/internal/query/types/jsonExtractor"
2025-01-20 13:31:48 +00:00
"github.com/google/uuid"
2025-01-03 13:41:07 +00:00
)
func (s *Service) Update(ctx context.Context, entity *queryprocessor.Update) error {
2025-01-03 16:00:36 +00:00
current, err := s.Get(ctx, entity.ID)
2025-01-03 13:41:07 +00:00
if err != nil {
return err
}
2025-01-20 13:31:48 +00:00
err = s.normalizeUpdate(ctx, current, entity)
if err != nil {
return err
}
err = s.submitUpdate(ctx, current, entity)
if err != nil {
return err
}
return nil
}
func (s *Service) normalizeUpdate(ctx context.Context, current *Query, entity *queryprocessor.Update) error {
err := s.normalizeActiveVersion(current, entity)
if err != nil {
return err
}
2025-01-23 14:56:20 +00:00
err = s.NormalizeQueryIDs(ctx, entity)
2025-01-20 13:31:48 +00:00
if err != nil {
return err
}
2025-01-23 14:56:20 +00:00
if entity.RequiredQueryIDs != nil {
createsloop, err := s.db.Queries.IsQueryInDependencyTree(ctx, &repository.IsQueryInDependencyTreeParams{
Requiredqueryid: database.MustToDBUUID(current.ID),
ID: database.MustToDBUUIDArray(*entity.RequiredQueryIDs),
})
if err != nil {
return err
} else if createsloop {
return errors.New("required ids create a loop")
}
}
2025-01-20 13:31:48 +00:00
err = s.normalizeConfig(entity)
if err != nil {
return err
}
2025-01-23 14:56:20 +00:00
if entity.ActiveVersion == nil &&
entity.RequiredQueryIDs == nil &&
entity.Config == nil {
return errors.New("no changes")
}
2025-01-03 16:00:36 +00:00
validator, err := s.getUpdator(current.Type)
2025-01-03 13:41:07 +00:00
if err != nil {
return err
}
2025-01-03 16:00:36 +00:00
err = validator.Validate(ctx, ParseQuery(current), entity)
2025-01-03 13:41:07 +00:00
if err != nil {
return err
}
2025-01-20 13:31:48 +00:00
return nil
}
func (s *Service) submitUpdate(ctx context.Context, current *Query, entity *queryprocessor.Update) error {
tx, err := s.db.Pool.Begin(ctx)
2025-01-06 14:40:43 +00:00
if err != nil {
return err
}
2025-01-20 13:31:48 +00:00
defer func() {
_ = tx.Rollback(ctx)
}()
qtx := s.db.Queries.WithTx(tx)
latestVersion := current.LatestVersion + 1
id := database.MustToDBUUID(entity.ID)
addIDs := getSetDifference(entity.RequiredQueryIDs, current.RequiredQueryIDs)
for _, qID := range addIDs {
err = qtx.AddRequiredQuery(ctx, &repository.AddRequiredQueryParams{
Queryid: id,
Requiredqueryid: database.MustToDBUUID(qID),
Addedversion: latestVersion,
})
if err != nil {
return err
}
}
removeIDs := getSetDifference(current.RequiredQueryIDs, entity.RequiredQueryIDs)
for _, qID := range removeIDs {
err = qtx.RemoveRequiredQuery(ctx, &repository.RemoveRequiredQueryParams{
Queryid: id,
Requiredqueryid: database.MustToDBUUID(qID),
Removedversion: &latestVersion,
})
if err != nil {
return err
}
}
if entity.Config != nil && *entity.Config != "" {
err = qtx.RemoveQueryConfig(ctx, &repository.RemoveQueryConfigParams{
Queryid: id,
Removedversion: &latestVersion,
})
if err != nil {
return err
}
err = qtx.AddQueryConfig(ctx, &repository.AddQueryConfigParams{
Queryid: id,
Config: []byte(*entity.Config),
Addedversion: latestVersion,
})
if err != nil {
return err
}
}
2025-01-23 14:56:20 +00:00
activeVersion := entity.ActiveVersion
if activeVersion == nil {
activeVersion = &current.ActiveVersion
2025-01-20 13:31:48 +00:00
}
2025-01-23 14:56:20 +00:00
err = qtx.UpdateQuery(ctx, &repository.UpdateQueryParams{
Latestversion: latestVersion,
Activeversion: *activeVersion,
ID: id,
})
if err != nil {
return err
2025-01-20 13:31:48 +00:00
}
2025-01-23 14:56:20 +00:00
err = tx.Commit(ctx)
if err != nil {
return err
2025-01-20 13:31:48 +00:00
}
2025-01-06 14:40:43 +00:00
2025-01-06 13:30:20 +00:00
return nil
}
2025-01-20 13:31:48 +00:00
func getSetDifference(setA *[]uuid.UUID, setB *[]uuid.UUID) []uuid.UUID {
if setA == nil {
return []uuid.UUID{}
} else if setB == nil {
return *setA
}
diff := []uuid.UUID{}
for _, q := range *setA {
isFound := false
for _, eq := range *setB {
if q == eq {
isFound = true
break
}
}
if !isFound {
diff = append(diff, q)
}
}
return diff
2025-01-03 13:41:07 +00:00
}
func (s *Service) getUpdator(qType queryprocessor.Type) (queryprocessor.Updator, error) {
switch qType {
case queryprocessor.TypeJsonExtractor:
return jsonextractor.NewUpdator(s.db), nil
case queryprocessor.TypeContextFull:
return contextfull.NewUpdator(s.db), nil
default:
return nil, fmt.Errorf("attempting to process invalid query type")
}
}
2025-01-03 16:00:36 +00:00
func ParseQuery(q *Query) *queryprocessor.Query {
return &queryprocessor.Query{
ID: q.ID,
Type: q.Type,
Version: q.ActiveVersion,
RequiredQueryIDs: q.RequiredQueryIDs,
Config: q.Config,
}
}