Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/implement update delete service request #47

Merged
merged 12 commits into from
Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 103 additions & 7 deletions backend/src/api/handlers/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
handlermodels "github.com/joshtyf/flowforge/src/api/handlers/models"
"github.com/joshtyf/flowforge/src/database"
"github.com/joshtyf/flowforge/src/database/client"
"github.com/joshtyf/flowforge/src/database/models"
dbmodels "github.com/joshtyf/flowforge/src/database/models"
"github.com/joshtyf/flowforge/src/events"
"github.com/joshtyf/flowforge/src/logger"
Expand All @@ -33,14 +34,17 @@ func HealthCheck(w http.ResponseWriter, r *http.Request) {
func GetAllServiceRequest(w http.ResponseWriter, r *http.Request) {
client, err := client.GetMongoClient()
if err != nil {
JSONError(w, handlermodels.NewHttpError(err), http.StatusInternalServerError)
logger.Error("[GetAllServiceRequest] Unable to get mongo client", map[string]interface{}{"err": err})
JSONError(w, handlermodels.NewHttpError(errors.New("internal server error")), http.StatusInternalServerError)
return
}
allsr, err := database.NewServiceRequest(client).GetAll()
if err != nil {
JSONError(w, handlermodels.NewHttpError(err), http.StatusInternalServerError)
logger.Error("[GetAllServiceRequest] Error retrieving all service request", map[string]interface{}{"err": err})
JSONError(w, handlermodels.NewHttpError(errors.New("internal server error")), http.StatusInternalServerError)
return
}
logger.Info("[GetAllServiceRequest] Successfully retrieved service requests", map[string]interface{}{"count": len(allsr)})
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(allsr)
w.WriteHeader(http.StatusOK)
Expand All @@ -49,17 +53,20 @@ func GetAllServiceRequest(w http.ResponseWriter, r *http.Request) {
func GetServiceRequest(w http.ResponseWriter, r *http.Request) {
client, err := client.GetMongoClient()
if err != nil {
JSONError(w, handlermodels.NewHttpError(err), http.StatusInternalServerError)
logger.Error("[GetServiceRequest] Unable to get mongo client", map[string]interface{}{"err": err})
JSONError(w, handlermodels.NewHttpError(errors.New("internal server error")), http.StatusInternalServerError)
return
}
vars := mux.Vars(r)
requestId := vars["requestId"]
sr, err := database.NewServiceRequest(client).GetById(requestId)
w.Header().Set("Content-Type", "application/json")
if err != nil {
JSONError(w, handlermodels.NewHttpError(err), http.StatusBadRequest)
logger.Error("[GetServiceRequest] Unable to retrieve service request", map[string]interface{}{"err": err})
JSONError(w, handlermodels.NewHttpError(errors.New("internal server error")), http.StatusBadRequest)
return
}
logger.Info("[GetServiceRequest] Successfully retrieved service request", map[string]interface{}{"sr": sr})
json.NewEncoder(w).Encode(sr)
w.WriteHeader(http.StatusOK)
return
Expand All @@ -68,7 +75,8 @@ func GetServiceRequest(w http.ResponseWriter, r *http.Request) {
func CreateServiceRequest(w http.ResponseWriter, r *http.Request) {
client, err := client.GetMongoClient()
if err != nil {
JSONError(w, handlermodels.NewHttpError(err), http.StatusInternalServerError)
logger.Error("[CreateServiceRequest] Unable to get mongo client", map[string]interface{}{"err": err})
JSONError(w, handlermodels.NewHttpError(errors.New("internal server error")), http.StatusInternalServerError)
return
}
srm := &dbmodels.ServiceRequestModel{
Expand All @@ -79,20 +87,107 @@ func CreateServiceRequest(w http.ResponseWriter, r *http.Request) {
err = json.NewDecoder(r.Body).Decode(srm)
w.Header().Set("Content-Type", "application/json")
if err != nil {
JSONError(w, handlermodels.NewHttpError(err), http.StatusBadRequest)
logger.Error("[CreateServiceRequest] Unable to parse json request body", map[string]interface{}{"err": err})
JSONError(w, handlermodels.NewHttpError(errors.New("unable to parse json request body")), http.StatusBadRequest)
return
}
res, err := database.NewServiceRequest(client).Create(srm)
if err != nil {
JSONError(w, handlermodels.NewHttpError(err), http.StatusInternalServerError)
logger.Error("[CreateServiceRequest] Error creating service request", map[string]interface{}{"err": err})
JSONError(w, handlermodels.NewHttpError(errors.New("internal server error")), http.StatusInternalServerError)
return
}
insertedId, _ := res.InsertedID.(primitive.ObjectID)
srm.Id = insertedId
logger.Info("[CreateServiceRequest] Successfully created service request", map[string]interface{}{"sr": srm})
event.FireAsync(events.NewNewServiceRequestEvent(srm))
w.WriteHeader(http.StatusCreated)
}

func CancelStartedServiceRequest(w http.ResponseWriter, r *http.Request) {
client, err := client.GetMongoClient()
if err != nil {
logger.Error("[CancelStartedServiceRequest] Unable to get mongo client", map[string]interface{}{"err": err})
JSONError(w, handlermodels.NewHttpError(errors.New("internal server error")), http.StatusInternalServerError)
return
}
vars := mux.Vars(r)
requestId := vars["requestId"]
sr, err := database.NewServiceRequest(client).GetById(requestId)
if err != nil {
logger.Error("[CancelStartedServiceRequest] Error getting service request", map[string]interface{}{"err": err})
JSONError(w, handlermodels.NewHttpError(errors.New("internal server error")), http.StatusInternalServerError)
return
}
status := sr.Status
w.Header().Set("Content-Type", "application/json")
if status != models.Pending && status != models.Running {
logger.Error("[CancelStartedServiceRequest] Unable to cancel service request as execution has been completed", nil)
JSONError(w, handlermodels.NewHttpError(errors.New("service request execution has been completed")), http.StatusBadRequest)
return
}
Comment on lines +125 to +129
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just check for status == models.Completed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because the cancellation can happen in the middle of the execution, where maybe the execution is at a pending approval step, and if the status is already completed, means the sr execution completed already what so what is there to cancel


if status == models.NotStarted {
logger.Error("[CancelStartedServiceRequest] Unable to cancel service request as execution has not been started", nil)
JSONError(w, handlermodels.NewHttpError(errors.New("service request execution has not been started")), http.StatusBadRequest)
return
}

// TODO: implement cancellation of sr

err = database.NewServiceRequest(client).UpdateStatus(requestId, models.Canceled)

// TODO: discuss how to handle this error
if err != nil {
logger.Error("[CancelStartedServiceRequest] Unable to update service request status", map[string]interface{}{"err": err})
JSONError(w, handlermodels.NewHttpError(errors.New("internal server error")), http.StatusInternalServerError)
return
}

logger.Info("[CancelStartedServiceRequest] Successfully canceled started service request", nil)
w.WriteHeader(http.StatusOK)
return
}

func UpdateServiceRequest(w http.ResponseWriter, r *http.Request) {
client, err := client.GetMongoClient()
if err != nil {
logger.Error("[UpdateServiceRequest] Unable to get mongo client", map[string]interface{}{"err": err})
JSONError(w, handlermodels.NewHttpError(errors.New("internal server error")), http.StatusInternalServerError)
return
}
srm := &dbmodels.ServiceRequestModel{}
err = json.NewDecoder(r.Body).Decode(srm)
w.Header().Set("Content-Type", "application/json")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually why do we still set this here when you already set it inside the JSONError method?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I specify in case we need to return a response that is not an error.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay. then maybe we need a new method for returning data

if err != nil {
logger.Error("[UpdateServiceRequest] Unable to parse json request body", map[string]interface{}{"err": err})
JSONError(w, handlermodels.NewHttpError(errors.New("unable to parse json request body")), http.StatusBadRequest)
return
}
vars := mux.Vars(r)
requestId := vars["requestId"]
sr, err := database.NewServiceRequest(client).GetById(requestId)
if err != nil {
logger.Error("[UpdateServiceRequest] Error getting service request", map[string]interface{}{"err": err})
JSONError(w, handlermodels.NewHttpError(errors.New("internal server error")), http.StatusInternalServerError)
return
}
status := sr.Status
if status != models.NotStarted {
logger.Error("[UpdateServiceRequest] Unable to update service request as service request has been started", nil)
JSONError(w, handlermodels.NewHttpError(errors.New("service request has been started")), http.StatusBadRequest)
return
}
res, err := database.NewServiceRequest(client).UpdateById(requestId, srm)
if err != nil {
logger.Error("[UpdateServiceRequest] Error updating service request", map[string]interface{}{"err": err})
JSONError(w, handlermodels.NewHttpError(errors.New("internal server error")), http.StatusInternalServerError)
return
}
logger.Info("[UpdateServiceRequest] Successfully updated service request", map[string]interface{}{"count": res.ModifiedCount})
w.WriteHeader(http.StatusOK)
}

func CreatePipeline(w http.ResponseWriter, r *http.Request) {
pipeline := &dbmodels.PipelineModel{
CreatedOn: time.Now(),
Expand All @@ -102,6 +197,7 @@ func CreatePipeline(w http.ResponseWriter, r *http.Request) {
if err != nil {
logger.Error("[CreatePipeline] Unable to parse json request body", map[string]interface{}{"err": err})
JSONError(w, handlermodels.NewHttpError(errors.New("unable to parse json request body")), http.StatusBadRequest)
return
}
client, err := client.GetMongoClient()
if err != nil {
Expand Down
10 changes: 6 additions & 4 deletions backend/src/database/models/service_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import (
type ServiceRequestStatus string

const (
Pending ServiceRequestStatus = "Pending"
Running ServiceRequestStatus = "Running"
Success ServiceRequestStatus = "Success"
Failure ServiceRequestStatus = "Failure"
Pending ServiceRequestStatus = "Pending"
Running ServiceRequestStatus = "Running"
Success ServiceRequestStatus = "Success"
Failure ServiceRequestStatus = "Failure"
Canceled ServiceRequestStatus = "Canceled"
NotStarted ServiceRequestStatus = "Not Started"
)

type ServiceRequestModel struct {
Expand Down
21 changes: 20 additions & 1 deletion backend/src/database/service_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,25 @@ func (sr *ServiceRequest) GetById(id string) (*models.ServiceRequestModel, error
return srm, nil
}

func (sr *ServiceRequest) UpdateById(id string, srm *models.ServiceRequestModel) (*mongo.UpdateResult, error) {
// TODO: update the method once form data is finalised
// objectId, _ := primitive.ObjectIDFromHex(id)
// filter := bson.M{"_id": objectId}
// update := bson.M{"$set": bson.M{
// "pipeline_id": srm.PipelineId,
// "pipeline_version": srm.PipelineVersion,
// "last_updated": srm.LastUpdated,
// "remarks": srm.Remarks}}

// res, err := sr.c.Database(DatabaseName).Collection("service_requests").UpdateOne(context.Background(), filter, update)
// if err != nil {
// return nil, err
// }
// return res, nil

return nil, nil
}

func (sr *ServiceRequest) GetAll() ([]*models.ServiceRequestModel, error) {
result, err := sr.c.Database(DatabaseName).Collection("service_requests").Find(context.Background(), bson.M{})
if err != nil {
Expand All @@ -55,4 +74,4 @@ func (sr *ServiceRequest) UpdateStatus(id string, status models.ServiceRequestSt
_, err = sr.c.Database(DatabaseName).Collection("service_requests").UpdateOne(
context.Background(), bson.M{"_id": objectId}, bson.M{"$set": bson.M{"status": status}})
return err
}
}
2 changes: 2 additions & 0 deletions backend/src/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ func main() {
r.HandleFunc("/api/healthcheck", handlers.HealthCheck).Methods("GET")
r.HandleFunc("/api/servicerequest/new", handlers.CreateServiceRequest).Methods("POST").Headers("Content-Type", "application/json")
r.HandleFunc("/api/servicerequest/{requestId}", handlers.GetServiceRequest).Methods("GET")
r.HandleFunc("/api/servicerequest/{requestId}/cancel", handlers.CancelStartedServiceRequest).Methods("GET")
r.HandleFunc("/api/servicerequest/{requestId}", handlers.UpdateServiceRequest).Methods("PATCH").Headers("Content-Type", "application/json")
r.HandleFunc("/api/servicerequest", handlers.GetAllServiceRequest).Methods("GET")
r.HandleFunc("/api/pipeline", handlers.CreatePipeline).Methods("POST").Headers("Content-Type", "application/json")
r.HandleFunc("/api/pipeline", handlers.GetAllPipelines).Methods("GET")
Expand Down
Loading