From ed1f0e770311d77a473e2f724d6d3139198bd215 Mon Sep 17 00:00:00 2001 From: Mariem Baccari Date: Wed, 19 Aug 2026 16:48:56 +0200 Subject: [PATCH] [raft/scd] Extract get and query opintent --- pkg/scd/actions/operational_intents.go | 96 ++++++++++++++++++++++++++ pkg/scd/operational_intents_handler.go | 53 ++------------ 2 files changed, 100 insertions(+), 49 deletions(-) create mode 100644 pkg/scd/actions/operational_intents.go diff --git a/pkg/scd/actions/operational_intents.go b/pkg/scd/actions/operational_intents.go new file mode 100644 index 000000000..4fe5ef6b3 --- /dev/null +++ b/pkg/scd/actions/operational_intents.go @@ -0,0 +1,96 @@ +package actions + +import ( + "context" + + restapi "github.com/interuss/dss/pkg/api/scdv1" + dsserr "github.com/interuss/dss/pkg/errors" + dssmodels "github.com/interuss/dss/pkg/models" + scdmodels "github.com/interuss/dss/pkg/scd/models" + "github.com/interuss/dss/pkg/scd/repos" + dssstore "github.com/interuss/dss/pkg/store" + "github.com/interuss/stacktrace" +) + +func init() { + Registry[restapi.GetOperationalIntentReferenceOperationID] = dssstore.OperationHandler[repos.Repository]{ + Encode: dssstore.EncodeJSON, + Decode: dssstore.DecodeJSON[*restapi.GetOperationalIntentReferenceRequest], + Execute: ExecuteGetOperationalIntentReference, + IsReadOnly: true, + } + Registry[restapi.QueryOperationalIntentReferencesOperationID] = dssstore.OperationHandler[repos.Repository]{ + Encode: dssstore.EncodeJSON, + Decode: dssstore.DecodeJSON[*restapi.QueryOperationalIntentReferencesRequest], + Execute: ExecuteQueryOperationalIntentReferences, + IsReadOnly: true, + } +} + +func ExecuteGetOperationalIntentReference(ctx context.Context, repo repos.Repository, request dssstore.OperationRequest) (any, error) { + req, ok := request.(*restapi.GetOperationalIntentReferenceRequest) + if !ok { + return nil, stacktrace.NewError("unexpected request type %T for operation %q", request, restapi.GetOperationalIntentReferenceOperationID) + } + + id, err := dssmodels.IDFromString(string(req.Entityid)) + if err != nil { + return nil, stacktrace.NewErrorWithCode(dsserr.BadRequest, "Invalid ID format: `%s`", req.Entityid) + } + + op, err := repo.GetOperationalIntent(ctx, id) + if err != nil { + return nil, stacktrace.Propagate(err, "Unable to get OperationalIntent from repo") + } + if op == nil { + return nil, stacktrace.NewErrorWithCode(dsserr.NotFound, "OperationalIntent %s not found", id) + } + + if op.Manager != dssmodels.Manager(*req.Auth.ClientID) { + op.OVN = scdmodels.NoOvnPhrase + } + + return &restapi.GetOperationalIntentReferenceResponse{ + OperationalIntentReference: *op.ToRest(), + }, nil +} + +func ExecuteQueryOperationalIntentReferences(ctx context.Context, repo repos.Repository, request dssstore.OperationRequest) (any, error) { + req, ok := request.(*restapi.QueryOperationalIntentReferencesRequest) + if !ok { + return nil, stacktrace.NewError("unexpected request type %T for operation %q", request, restapi.QueryOperationalIntentReferencesOperationID) + } + + // Retrieve the area of interest parameter + aoi := req.Body.AreaOfInterest + if aoi == nil { + return nil, stacktrace.NewErrorWithCode(dsserr.BadRequest, "Missing area_of_interest") + } + + // Parse area of interest to common Volume4D + vol4, err := scdmodels.Volume4DFromSCDRest(aoi) + if err != nil { + return nil, stacktrace.PropagateWithCode(err, dsserr.BadRequest, "Error parsing geometry") + } + + // Perform search query on Store + ops, err := repo.SearchOperationalIntents(ctx, vol4) + if err != nil { + return nil, stacktrace.Propagate(err, "Unable to query for OperationalIntents in repo") + } + + // Create response for client + response := &restapi.QueryOperationalIntentReferenceResponse{ + OperationalIntentReferences: make([]restapi.OperationalIntentReference, 0, len(ops)), + } + for _, op := range ops { + p := op.ToRest() + if op.Manager != dssmodels.Manager(*req.Auth.ClientID) { + noOvnPhrase := restapi.EntityOVN(scdmodels.NoOvnPhrase) + p.Ovn = &noOvnPhrase + } + response.OperationalIntentReferences = append(response.OperationalIntentReferences, *p) + } + + return response, nil +} diff --git a/pkg/scd/operational_intents_handler.go b/pkg/scd/operational_intents_handler.go index 33c6c0ef8..73762e55c 100644 --- a/pkg/scd/operational_intents_handler.go +++ b/pkg/scd/operational_intents_handler.go @@ -190,7 +190,7 @@ func (a *Server) DeleteOperationalIntentReference(ctx context.Context, req *rest func (a *Server) GetOperationalIntentReference(ctx context.Context, req *restapi.GetOperationalIntentReferenceRequest, ) restapi.GetOperationalIntentReferenceResponseSet { - id, err := dssmodels.IDFromString(string(req.Entityid)) + _, err := dssmodels.IDFromString(string(req.Entityid)) if err != nil { return restapi.GetOperationalIntentReferenceResponseSet{Response400: &restapi.ErrorResponse{ Message: dsserr.Handle(ctx, stacktrace.NewErrorWithCode(dsserr.BadRequest, "Invalid ID format: `%s`", req.Entityid))}} @@ -201,28 +201,7 @@ func (a *Server) GetOperationalIntentReference(ctx context.Context, req *restapi Message: dsserr.Handle(ctx, stacktrace.NewErrorWithCode(dsserr.PermissionDenied, "Missing manager"))}} } - var response *restapi.GetOperationalIntentReferenceResponse - action := func(ctx context.Context, r repos.Repository) (err error) { - op, err := r.GetOperationalIntent(ctx, id) - if err != nil { - return stacktrace.Propagate(err, "Unable to get OperationalIntent from repo") - } - if op == nil { - return stacktrace.NewErrorWithCode(dsserr.NotFound, "OperationalIntent %s not found", id) - } - - if op.Manager != dssmodels.Manager(*req.Auth.ClientID) { - op.OVN = scdmodels.NoOvnPhrase - } - - response = &restapi.GetOperationalIntentReferenceResponse{ - OperationalIntentReference: *op.ToRest(), - } - - return nil - } - - _, err = a.Store.Transact(ctx, dssstore.NewFuncOperation(action)) + response, err := dssstore.TransactWithResult[repos.Repository, *restapi.GetOperationalIntentReferenceResponse](ctx, a.Store, req) if err != nil { err = stacktrace.Propagate(err, "Could not get operational intent") if stacktrace.GetCode(err) == dsserr.NotFound { @@ -253,7 +232,7 @@ func (a *Server) QueryOperationalIntentReferences(ctx context.Context, req *rest } // Parse area of interest to common Volume4D - vol4, err := scdmodels.Volume4DFromSCDRest(aoi) + _, err := scdmodels.Volume4DFromSCDRest(aoi) if err != nil { return restapi.QueryOperationalIntentReferencesResponseSet{Response400: &restapi.ErrorResponse{ Message: dsserr.Handle(ctx, stacktrace.PropagateWithCode(err, dsserr.BadRequest, "Error parsing geometry"))}} @@ -265,31 +244,7 @@ func (a *Server) QueryOperationalIntentReferences(ctx context.Context, req *rest Message: dsserr.Handle(ctx, stacktrace.NewErrorWithCode(dsserr.PermissionDenied, "Missing manager"))}} } - var response *restapi.QueryOperationalIntentReferenceResponse - action := func(ctx context.Context, r repos.Repository) (err error) { - // Perform search query on Store - ops, err := r.SearchOperationalIntents(ctx, vol4) - if err != nil { - return stacktrace.Propagate(err, "Unable to query for OperationalIntents in repo") - } - - // Create response for client - response = &restapi.QueryOperationalIntentReferenceResponse{ - OperationalIntentReferences: make([]restapi.OperationalIntentReference, 0, len(ops)), - } - for _, op := range ops { - p := op.ToRest() - if op.Manager != dssmodels.Manager(*req.Auth.ClientID) { - noOvnPhrase := restapi.EntityOVN(scdmodels.NoOvnPhrase) - p.Ovn = &noOvnPhrase - } - response.OperationalIntentReferences = append(response.OperationalIntentReferences, *p) - } - - return nil - } - - _, err = a.Store.Transact(ctx, dssstore.NewFuncOperation(action)) + response, err := dssstore.TransactWithResult[repos.Repository, *restapi.QueryOperationalIntentReferenceResponse](ctx, a.Store, req) if err != nil { err = stacktrace.Propagate(err, "Could not query operational intent") if stacktrace.GetCode(err) == dsserr.BadRequest {