diff --git a/internal/datastore/mongo_store.go b/internal/datastore/mongo_store.go index ff6c4c8..af88940 100644 --- a/internal/datastore/mongo_store.go +++ b/internal/datastore/mongo_store.go @@ -2,11 +2,13 @@ package datastore import ( "context" + "errors" "log" "os" "github.com/SimplQ/simplQ-golang/internal/models" + "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" @@ -46,35 +48,70 @@ func NewMongoDB() *MongoDB { return &new_mongodb } -func (mongodb MongoDB) CreateQueue(queue models.Queue) models.QueueId { +func (mongodb MongoDB) CreateQueue(queue models.Queue) (models.QueueId, error) { // Set id to empty so its generated by mongoDB queue.Id = "" result, err := mongodb.Queue.InsertOne(context.TODO(), queue) if err != nil { - log.Fatal(err) + return queue.Id, err } stringId := result.InsertedID.(primitive.ObjectID).Hex() - return models.QueueId(stringId) + return models.QueueId(stringId), nil } -func (mongodb MongoDB) ReadQueue(models.QueueId) models.Queue { - panic("Not implemented") -} +func (mongodb MongoDB) ReadQueue(id models.QueueId) (models.Queue, error) { + result := models.Queue{} -func (mongodb MongoDB) PauseQueue(models.QueueId) { - panic("Not implemented") + // convert id string to ObjectId + queueId, _ := primitive.ObjectIDFromHex(string(id)) + + err := mongodb.Queue.FindOne(context.TODO(), bson.M{"_id": queueId}).Decode(&result) + + if err != nil { + return result, err + } + + return result, nil } -func (mongodb MongoDB) ResumeQueue(models.QueueId) { - panic("Not implemented") +func (mongodb MongoDB) SetIsPaused(id models.QueueId, isPaused bool) error { + queueId, _ := primitive.ObjectIDFromHex(string(id)) + result, err := mongodb.Queue.UpdateOne( + context.TODO(), + bson.M{"_id": queueId}, + bson.D{ + {Key: "$set", Value: bson.D{primitive.E{Key: "isPaused", Value: isPaused}}}, + }, + ) + if err != nil { + return err + } + log.Printf("Records updated:%d", result.ModifiedCount) + if result.ModifiedCount == 0 { + return errors.New("no record found") + } + return nil + } -func (mongodb MongoDB) DeleteQueue(models.QueueId) { - panic("Not implemented") +func (mongodb MongoDB) DeleteQueue(id models.QueueId) error { + queueId, _ := primitive.ObjectIDFromHex(string(id)) + result, err := mongodb.Queue.DeleteOne( + context.TODO(), + bson.M{"_id": queueId}) + + if err != nil { + return err + } + log.Printf("Records deleted:%d", result.DeletedCount) + if result.DeletedCount == 0 { + return errors.New("no record found") + } + return nil } func (mongodb MongoDB) AddTokenToQueue(models.QueueId, models.Token) { diff --git a/internal/datastore/store.go b/internal/datastore/store.go index bd13515..6b37baa 100644 --- a/internal/datastore/store.go +++ b/internal/datastore/store.go @@ -1,22 +1,21 @@ package datastore -import "github.com/SimplQ/simplQ-golang/internal/models" +import ( + "github.com/SimplQ/simplQ-golang/internal/models" +) type QueueStore interface { // Create a new queue and return the queue ID. - CreateQueue(models.Queue) models.QueueId + CreateQueue(models.Queue) (models.QueueId, error) // Read a queue by id. - ReadQueue(models.QueueId) models.Queue + ReadQueue(models.QueueId) (models.Queue, error) - // Set the queue pause status to true - PauseQueue(models.QueueId) - - // Set the queue pause status to false - ResumeQueue(models.QueueId) + // Set the queue pause status to true/false + SetIsPaused(models.QueueId, bool) error // Set the queue delete status to new value. - DeleteQueue(models.QueueId) + DeleteQueue(models.QueueId) error // Add a new token to the queue. AddTokenToQueue(models.QueueId, models.Token) diff --git a/internal/handler/queue.go b/internal/handler/queue.go index 59fb94c..62ccf4a 100644 --- a/internal/handler/queue.go +++ b/internal/handler/queue.go @@ -1,6 +1,7 @@ package handler import ( + "context" "encoding/json" "fmt" "log" @@ -9,10 +10,25 @@ import ( "github.com/SimplQ/simplQ-golang/internal/datastore" "github.com/SimplQ/simplQ-golang/internal/models" + "github.com/go-chi/chi/v5" ) +type key int + +const queueId key = 0 + func GetQueue(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "GET Queue not implemented") + id := r.Context().Value(queueId).(string) + if id == "" { + http.Error(w, fmt.Sprintf("Invalid Id: %s", id), http.StatusBadRequest) + return + } + queue, err := datastore.Store.ReadQueue(models.QueueId(id)) + if err != nil { + http.Error(w, fmt.Sprint(err), http.StatusInternalServerError) + return + } + json.NewEncoder(w).Encode(queue) } func CreateQueue(w http.ResponseWriter, r *http.Request) { @@ -22,7 +38,7 @@ func CreateQueue(w http.ResponseWriter, r *http.Request) { err := decoder.Decode(&q) if err != nil { - panic(err) + http.Error(w, fmt.Sprint(err), http.StatusBadRequest) } // Initialize values @@ -32,12 +48,64 @@ func CreateQueue(w http.ResponseWriter, r *http.Request) { q.IsPaused = false q.Tokens = make([]models.Token, 0) - log.Print("Create Queue: ") - log.Println(q) + insertedId, err := datastore.Store.CreateQueue(q) + if err != nil { + http.Error(w, fmt.Sprint(err), http.StatusInternalServerError) + return + } + log.Printf("Inserted %s", insertedId) + w.WriteHeader(http.StatusCreated) + fmt.Fprintf(w, "Queue created with Id: %s", insertedId) +} - insertedId := datastore.Store.CreateQueue(q) +func PauseQueue(w http.ResponseWriter, r *http.Request) { + id := r.Context().Value(queueId).(string) + if id == "" { + http.Error(w, fmt.Sprintf("Invalid Id: %s", id), http.StatusBadRequest) + return + } + err := datastore.Store.SetIsPaused(models.QueueId(id), true) // Set IsPaused = true + if err != nil { + http.Error(w, fmt.Sprint(err), http.StatusInternalServerError) + return + } + fmt.Fprintf(w, "Paused Queue Id: %s", id) + w.WriteHeader(http.StatusOK) +} - log.Printf("Inserted %s", insertedId) +func ResumeQueue(w http.ResponseWriter, r *http.Request) { + id := r.Context().Value(queueId).(string) + if id == "" { + http.Error(w, fmt.Sprintf("Invalid Id: %s", id), http.StatusBadRequest) + return + } + err := datastore.Store.SetIsPaused(models.QueueId(id), false) // Set IsPaused = false + if err != nil { + http.Error(w, fmt.Sprint(err), http.StatusInternalServerError) + return + } + fmt.Fprintf(w, "Resumed Queue Id: %s", id) + w.WriteHeader(http.StatusOK) +} + +func DeleteQueue(w http.ResponseWriter, r *http.Request) { + id := r.Context().Value(queueId).(string) + if id == "" { + http.Error(w, fmt.Sprintf("Invalid Id: %s", id), http.StatusBadRequest) + return + } + err := datastore.Store.DeleteQueue(models.QueueId(id)) + if err != nil { + http.Error(w, fmt.Sprint(err), http.StatusInternalServerError) + return + } + fmt.Fprintf(w, "Deleted Queue Id: %s", id) + w.WriteHeader(http.StatusOK) +} - fmt.Fprintf(w, "Post queue") +func QueueCtx(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), queueId, chi.URLParam(r, "id")) + next.ServeHTTP(w, r.WithContext(ctx)) + }) } diff --git a/internal/mux/mux.go b/internal/mux/mux.go index abeaa39..e62e488 100644 --- a/internal/mux/mux.go +++ b/internal/mux/mux.go @@ -23,7 +23,15 @@ func InitalizeRoutes() chi.Router { r.Route("/queue", func(r chi.Router) { // POST /articles r.Post("/", handler.CreateQueue) - }) + // Subrouters + r.Route("/{id}", func(r chi.Router) { + r.Use(handler.QueueCtx) + r.Get("/", handler.GetQueue) // GET /queue/123 + r.Put("/pause", handler.PauseQueue) // PUT /queue/123/pause + r.Put("/resume", handler.ResumeQueue) // PUT /queue/123/resume + r.Delete("/", handler.DeleteQueue) // DELETE /queue/123 + }) + }) return r }