From d14e8b8a970b31110eebb2d7205aa663c2f41632 Mon Sep 17 00:00:00 2001 From: Sijin Pavithran Date: Sat, 1 Jan 2022 15:43:29 +0000 Subject: [PATCH 01/10] Added read, pause, resume and delete for queue --- internal/datastore/mongo_store.go | 126 ++++++++++++++++++++---------- internal/handler/queue.go | 85 +++++++++++++++----- internal/mux/mux.go | 21 ++++- 3 files changed, 169 insertions(+), 63 deletions(-) diff --git a/internal/datastore/mongo_store.go b/internal/datastore/mongo_store.go index 6d3ee17..dd1cace 100644 --- a/internal/datastore/mongo_store.go +++ b/internal/datastore/mongo_store.go @@ -2,11 +2,13 @@ package datastore import ( "context" + "fmt" "log" - "os" + "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" @@ -14,77 +16,117 @@ import ( // A Structure with Collections frequently used and a pointer to the client type MongoDB struct { - Client *mongo.Client - Queue *mongo.Collection - Token *mongo.Collection + Client *mongo.Client + Queue *mongo.Collection + Token *mongo.Collection } func NewMongoDB() *MongoDB { - // Use local development mongodb instance if env variable not set - uri := "mongodb://root:example@localhost:27017/?maxPoolSize=20&w=majority" - - if val, ok := os.LookupEnv("MONGO_URI"); ok { - uri = val + // Use local development mongodb instance if env variable not set + uri := "mongodb://root:example@localhost:27017/?maxPoolSize=20&w=majority" + + if val, ok := os.LookupEnv("MONGO_URI"); ok { + uri = val } - log.Println("Connecting to MongoDB...") + log.Println("Connecting to MongoDB...") + + client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri)) - client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri)) - - if err != nil { - log.Fatal(err) - } + if err != nil { + log.Fatal(err) + } - new_mongodb := MongoDB { - client, - client.Database("simplq").Collection("queue"), - client.Database("simplq").Collection("token"), - } + new_mongodb := MongoDB{ + client, + client.Database("simplq").Collection("queue"), + client.Database("simplq").Collection("token"), + } - log.Println("Successfully connected to MongoDB!") + log.Println("Successfully connected to MongoDB!") - return &new_mongodb + return &new_mongodb } func (mongodb MongoDB) CreateQueue(queue models.Queue) models.QueueId { - // Set id to empty so its generated by mongoDB - queue.Id = "" + // Set id to empty so its generated by mongoDB + queue.Id = "" - result, err := mongodb.Queue.InsertOne(context.TODO(), queue) + result, err := mongodb.Queue.InsertOne(context.TODO(), queue) - if err != nil { - log.Fatal(err) - } - - stringId := result.InsertedID.(primitive.ObjectID).Hex() + if err != nil { + log.Fatal(err) + } + + stringId := result.InsertedID.(primitive.ObjectID).Hex() - return models.QueueId(stringId) + return models.QueueId(stringId) } -func (mongodb MongoDB) ReadQueue(models.QueueId) models.Queue { - panic("Not implemented") +func (mongodb MongoDB) ReadQueue(id models.QueueId) models.Queue { + result := models.Queue{} + + // 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 { + log.Fatal(err) + } + + return result } -func (mongodb MongoDB) PauseQueue(models.QueueId) { - panic("Not implemented") +func (mongodb MongoDB) PauseQueue(id models.QueueId) { + queueId, _ := primitive.ObjectIDFromHex(string(id)) + result, err := mongodb.Queue.UpdateOne( + context.TODO(), + bson.M{"_id": queueId}, + bson.D{ + {"$set", bson.D{{"isPaused", true}}}, + }, + ) + if err != nil { + log.Fatal(err) + } + fmt.Printf("Paused %v Documents!\n", result.ModifiedCount) } -func (mongodb MongoDB) ResumeQueue(models.QueueId) { - panic("Not implemented") +func (mongodb MongoDB) ResumeQueue(id models.QueueId) { + queueId, _ := primitive.ObjectIDFromHex(string(id)) + result, err := mongodb.Queue.UpdateOne( + context.TODO(), + bson.M{"_id": queueId}, + bson.D{ + {"$set", bson.D{{"isPaused", false}}}, + }, + ) + if err != nil { + log.Fatal(err) + } + fmt.Printf("Resumed %v Documents!\n", result.ModifiedCount) } -func (mongodb MongoDB) DeleteQueue(models.QueueId) { - panic("Not implemented") +func (mongodb MongoDB) DeleteQueue(id models.QueueId) { + queueId, _ := primitive.ObjectIDFromHex(string(id)) + result, err := mongodb.Queue.DeleteOne( + context.TODO(), + bson.M{"_id": queueId}) + if err != nil { + log.Fatal(err) + } + fmt.Printf("Deleted %v Documents!\n", result.DeletedCount) } func (mongodb MongoDB) AddTokenToQueue(models.QueueId, models.Token) { - panic("Not implemented") + panic("Not implemented") } func (mongodb MongoDB) ReadToken(models.TokenId) { - panic("Not implemented") + panic("Not implemented") } func (mongodb MongoDB) RemoveToken(models.TokenId) { - panic("Not implemented") + panic("Not implemented") } diff --git a/internal/handler/queue.go b/internal/handler/queue.go index fb8d05c..c54ceb3 100644 --- a/internal/handler/queue.go +++ b/internal/handler/queue.go @@ -1,6 +1,7 @@ package handler import ( + "context" "encoding/json" "fmt" "log" @@ -9,35 +10,83 @@ import ( "github.com/SimplQ/simplQ-golang/internal/datastore" "github.com/SimplQ/simplQ-golang/internal/models" + "github.com/go-chi/chi/v5" ) func GetQueue(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "GET Queue not implemented") + id := r.Context().Value("id").(string) + if id == "" { + w.WriteHeader(http.StatusNotFound) + return + } + q := datastore.Store.ReadQueue(models.QueueId(id)) + json.NewEncoder(w).Encode(q) + fmt.Fprintf(w, "Get queue") } func CreateQueue(w http.ResponseWriter, r *http.Request) { - decoder := json.NewDecoder(r.Body) + decoder := json.NewDecoder(r.Body) - var q models.Queue - err := decoder.Decode(&q) + var q models.Queue + err := decoder.Decode(&q) - if err != nil { - panic(err) - } + if err != nil { + panic(err) + } - // Initialize values - // Only consider queue name from the body of the request - q.CreationTime = time.Now() - q.IsDeleted = false - q.IsPaused = false - q.Tokens = make([]models.Token, 0) + // Initialize values + // Only consider queue name from the body of the request + q.CreationTime = time.Now() + q.IsDeleted = false + q.IsPaused = false + q.Tokens = make([]models.Token, 0) - log.Print("Create Queue: ") - log.Println(q) + log.Print("Create Queue: ") + log.Println(q) - insertedId := datastore.Store.CreateQueue(q) + insertedId := datastore.Store.CreateQueue(q) - log.Printf("Inserted %s", insertedId) + log.Printf("Inserted %s", insertedId) - fmt.Fprintf(w, "Post queue") + fmt.Fprintf(w, "Post queue") +} + +func PauseQueue(w http.ResponseWriter, r *http.Request) { + id := r.Context().Value("id").(string) + if id == "" { + w.WriteHeader(http.StatusNotFound) + return + } + log.Println("URL path param 'id' is: " + string(id)) + datastore.Store.PauseQueue(models.QueueId(id)) + fmt.Fprintf(w, "Queue paused") +} + +func ResumeQueue(w http.ResponseWriter, r *http.Request) { + id := r.Context().Value("id").(string) + if id == "" { + w.WriteHeader(http.StatusNotFound) + return + } + log.Println("URL path param 'id' is: " + string(id)) + datastore.Store.ResumeQueue(models.QueueId(id)) + fmt.Fprintf(w, "Queue resumed") +} + +func DeleteQueue(w http.ResponseWriter, r *http.Request) { + id := r.Context().Value("id").(string) + if id == "" { + w.WriteHeader(http.StatusNotFound) + return + } + log.Println("URL path param 'id' is: " + string(id)) + datastore.Store.DeleteQueue(models.QueueId(id)) + fmt.Fprintf(w, "Delete queue") +} + +func QueueCtx(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), "id", chi.URLParam(r, "id")) + next.ServeHTTP(w, r.WithContext(ctx)) + }) } diff --git a/internal/mux/mux.go b/internal/mux/mux.go index c79bde7..1db6a99 100644 --- a/internal/mux/mux.go +++ b/internal/mux/mux.go @@ -22,8 +22,23 @@ func InitalizeRoutes() chi.Router { // Routes for "queue" resource r.Route("/queue", func(r chi.Router) { // POST /articles - r.Post("/", handler.CreateQueue) + r.Post("/", handler.CreateQueue) + + // Subrouters + r.Route("/{id}", func(r chi.Router) { + r.Use(handler.QueueCtx) + r.Get("/", handler.GetQueue) // GET /queue/123 + r.Delete("/", handler.DeleteQueue) // DELETE /queue/123 + }) + r.Route("/pause/{id}", func(r chi.Router) { + r.Use(handler.QueueCtx) + r.Put("/", handler.PauseQueue) // PUT /queue/pause/123 + + }) + r.Route("/resume/{id}", func(r chi.Router) { + r.Use(handler.QueueCtx) + r.Put("/", handler.ResumeQueue) // PUT /queue/resume/123 + }) }) - - return r; + return r } From 2d78b32ff3729ff30f79d2ebc803b20a387812b5 Mon Sep 17 00:00:00 2001 From: Sijin Pavithran Date: Tue, 11 Jan 2022 21:03:26 +0000 Subject: [PATCH 02/10] Changed /pause/{id} to /{id}/pause --- internal/mux/mux.go | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/internal/mux/mux.go b/internal/mux/mux.go index 1db6a99..e62e488 100644 --- a/internal/mux/mux.go +++ b/internal/mux/mux.go @@ -27,17 +27,10 @@ func InitalizeRoutes() chi.Router { // Subrouters r.Route("/{id}", func(r chi.Router) { r.Use(handler.QueueCtx) - r.Get("/", handler.GetQueue) // GET /queue/123 - r.Delete("/", handler.DeleteQueue) // DELETE /queue/123 - }) - r.Route("/pause/{id}", func(r chi.Router) { - r.Use(handler.QueueCtx) - r.Put("/", handler.PauseQueue) // PUT /queue/pause/123 - - }) - r.Route("/resume/{id}", func(r chi.Router) { - r.Use(handler.QueueCtx) - r.Put("/", handler.ResumeQueue) // PUT /queue/resume/123 + 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 From 175fe958a0571198de2961c1937478af598bac79 Mon Sep 17 00:00:00 2001 From: Sijin Pavithran Date: Tue, 11 Jan 2022 21:07:08 +0000 Subject: [PATCH 03/10] Removed Fprintf. Not needed --- internal/handler/queue.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/handler/queue.go b/internal/handler/queue.go index c54ceb3..6e68958 100644 --- a/internal/handler/queue.go +++ b/internal/handler/queue.go @@ -21,7 +21,6 @@ func GetQueue(w http.ResponseWriter, r *http.Request) { } q := datastore.Store.ReadQueue(models.QueueId(id)) json.NewEncoder(w).Encode(q) - fmt.Fprintf(w, "Get queue") } func CreateQueue(w http.ResponseWriter, r *http.Request) { From 201905416edfac60c9959e24898d644b6b83c677 Mon Sep 17 00:00:00 2001 From: Sijin Pavithran Date: Tue, 11 Jan 2022 22:43:43 +0000 Subject: [PATCH 04/10] Checks and error handling added for GetQueue --- internal/datastore/mongo_store.go | 6 +++--- internal/datastore/store.go | 2 +- internal/handler/queue.go | 10 +++++++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/internal/datastore/mongo_store.go b/internal/datastore/mongo_store.go index dd1cace..d59c7e4 100644 --- a/internal/datastore/mongo_store.go +++ b/internal/datastore/mongo_store.go @@ -63,7 +63,7 @@ func (mongodb MongoDB) CreateQueue(queue models.Queue) models.QueueId { return models.QueueId(stringId) } -func (mongodb MongoDB) ReadQueue(id models.QueueId) models.Queue { +func (mongodb MongoDB) ReadQueue(id models.QueueId) (models.Queue, error) { result := models.Queue{} // convert id string to ObjectId @@ -72,10 +72,10 @@ func (mongodb MongoDB) ReadQueue(id models.QueueId) models.Queue { err := mongodb.Queue.FindOne(context.TODO(), bson.M{"_id": queueId}).Decode(&result) if err != nil { - log.Fatal(err) + return result, err } - return result + return result, nil } func (mongodb MongoDB) PauseQueue(id models.QueueId) { diff --git a/internal/datastore/store.go b/internal/datastore/store.go index bd13515..620c435 100644 --- a/internal/datastore/store.go +++ b/internal/datastore/store.go @@ -7,7 +7,7 @@ type QueueStore interface { CreateQueue(models.Queue) models.QueueId // 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) diff --git a/internal/handler/queue.go b/internal/handler/queue.go index 6e68958..9a0bf47 100644 --- a/internal/handler/queue.go +++ b/internal/handler/queue.go @@ -16,11 +16,15 @@ import ( func GetQueue(w http.ResponseWriter, r *http.Request) { id := r.Context().Value("id").(string) if id == "" { - w.WriteHeader(http.StatusNotFound) + http.Error(w, fmt.Sprintf("Invalid Id: %s", id), 404) + return + } + queue, err := datastore.Store.ReadQueue(models.QueueId(id)) + if err != nil { + http.Error(w, fmt.Sprintf("No record found for Queue Id: %s", id), 404) return } - q := datastore.Store.ReadQueue(models.QueueId(id)) - json.NewEncoder(w).Encode(q) + json.NewEncoder(w).Encode(queue) } func CreateQueue(w http.ResponseWriter, r *http.Request) { From 4adf7e07083a28be6f61ccd3b59e72e4ddab23e5 Mon Sep 17 00:00:00 2001 From: Sijin Pavithran Date: Tue, 11 Jan 2022 23:05:42 +0000 Subject: [PATCH 05/10] Changed PauseQueue/ResumeQueue to setIsPaused --- internal/datastore/mongo_store.go | 23 +++++----------------- internal/datastore/store.go | 12 ++++++------ internal/handler/queue.go | 32 +++++++++++++++++++++++-------- 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/internal/datastore/mongo_store.go b/internal/datastore/mongo_store.go index d59c7e4..0dacd0b 100644 --- a/internal/datastore/mongo_store.go +++ b/internal/datastore/mongo_store.go @@ -78,34 +78,21 @@ func (mongodb MongoDB) ReadQueue(id models.QueueId) (models.Queue, error) { return result, nil } -func (mongodb MongoDB) PauseQueue(id models.QueueId) { +func (mongodb MongoDB) SetIsPaused(id models.QueueId, isPaused bool) (*mongo.UpdateResult, error) { queueId, _ := primitive.ObjectIDFromHex(string(id)) result, err := mongodb.Queue.UpdateOne( context.TODO(), bson.M{"_id": queueId}, bson.D{ - {"$set", bson.D{{"isPaused", true}}}, + {"$set", bson.D{{"isPaused", isPaused}}}, }, ) - if err != nil { - log.Fatal(err) - } - fmt.Printf("Paused %v Documents!\n", result.ModifiedCount) -} -func (mongodb MongoDB) ResumeQueue(id models.QueueId) { - queueId, _ := primitive.ObjectIDFromHex(string(id)) - result, err := mongodb.Queue.UpdateOne( - context.TODO(), - bson.M{"_id": queueId}, - bson.D{ - {"$set", bson.D{{"isPaused", false}}}, - }, - ) if err != nil { - log.Fatal(err) + return result, err } - fmt.Printf("Resumed %v Documents!\n", result.ModifiedCount) + + return result, nil } func (mongodb MongoDB) DeleteQueue(id models.QueueId) { diff --git a/internal/datastore/store.go b/internal/datastore/store.go index 620c435..cc1eb8a 100644 --- a/internal/datastore/store.go +++ b/internal/datastore/store.go @@ -1,6 +1,9 @@ package datastore -import "github.com/SimplQ/simplQ-golang/internal/models" +import ( + "github.com/SimplQ/simplQ-golang/internal/models" + "go.mongodb.org/mongo-driver/mongo" +) type QueueStore interface { // Create a new queue and return the queue ID. @@ -9,11 +12,8 @@ type QueueStore interface { // Read a queue by id. 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) (*mongo.UpdateResult, error) // Set the queue delete status to new value. DeleteQueue(models.QueueId) diff --git a/internal/handler/queue.go b/internal/handler/queue.go index 9a0bf47..57b7f8e 100644 --- a/internal/handler/queue.go +++ b/internal/handler/queue.go @@ -57,23 +57,39 @@ func CreateQueue(w http.ResponseWriter, r *http.Request) { func PauseQueue(w http.ResponseWriter, r *http.Request) { id := r.Context().Value("id").(string) if id == "" { - w.WriteHeader(http.StatusNotFound) + http.Error(w, fmt.Sprintf("Invalid Id: %s", id), 404) return } - log.Println("URL path param 'id' is: " + string(id)) - datastore.Store.PauseQueue(models.QueueId(id)) - fmt.Fprintf(w, "Queue paused") + result, err := datastore.Store.SetIsPaused(models.QueueId(id), true) // Set IsPaused = true + if err != nil { + http.Error(w, fmt.Sprint(err), 400) + return + } + if result.ModifiedCount == 0 { + http.Error(w, fmt.Sprintf("No record found for Queue Id: %s", id), 404) + return + } + fmt.Fprintf(w, "Paused Queue Id: %s", id) + w.WriteHeader(200) } func ResumeQueue(w http.ResponseWriter, r *http.Request) { id := r.Context().Value("id").(string) if id == "" { - w.WriteHeader(http.StatusNotFound) + http.Error(w, fmt.Sprintf("Invalid Id: %s", id), 404) return } - log.Println("URL path param 'id' is: " + string(id)) - datastore.Store.ResumeQueue(models.QueueId(id)) - fmt.Fprintf(w, "Queue resumed") + result, err := datastore.Store.SetIsPaused(models.QueueId(id), false) // Set IsPaused = false + if err != nil { + http.Error(w, fmt.Sprint(err), 400) + return + } + if result.ModifiedCount == 0 { + http.Error(w, fmt.Sprintf("No record found for Queue Id: %s", id), 404) + return + } + fmt.Fprintf(w, "Resumed Queue Id: %s", id) + w.WriteHeader(200) } func DeleteQueue(w http.ResponseWriter, r *http.Request) { From 315fd442e408fb783a7050c0eb349cc0b54374a9 Mon Sep 17 00:00:00 2001 From: Sijin Pavithran Date: Tue, 11 Jan 2022 23:12:54 +0000 Subject: [PATCH 06/10] Added error handling to delete queue --- internal/datastore/mongo_store.go | 8 ++++---- internal/datastore/store.go | 2 +- internal/handler/queue.go | 16 ++++++++++++---- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/internal/datastore/mongo_store.go b/internal/datastore/mongo_store.go index 0dacd0b..f44229a 100644 --- a/internal/datastore/mongo_store.go +++ b/internal/datastore/mongo_store.go @@ -2,7 +2,6 @@ package datastore import ( "context" - "fmt" "log" "os" @@ -95,15 +94,16 @@ func (mongodb MongoDB) SetIsPaused(id models.QueueId, isPaused bool) (*mongo.Upd return result, nil } -func (mongodb MongoDB) DeleteQueue(id models.QueueId) { +func (mongodb MongoDB) DeleteQueue(id models.QueueId) (*mongo.DeleteResult, error) { queueId, _ := primitive.ObjectIDFromHex(string(id)) result, err := mongodb.Queue.DeleteOne( context.TODO(), bson.M{"_id": queueId}) if err != nil { - log.Fatal(err) + return result, err } - fmt.Printf("Deleted %v Documents!\n", result.DeletedCount) + + return result, nil } func (mongodb MongoDB) AddTokenToQueue(models.QueueId, models.Token) { diff --git a/internal/datastore/store.go b/internal/datastore/store.go index cc1eb8a..3ed499b 100644 --- a/internal/datastore/store.go +++ b/internal/datastore/store.go @@ -16,7 +16,7 @@ type QueueStore interface { SetIsPaused(models.QueueId, bool) (*mongo.UpdateResult, error) // Set the queue delete status to new value. - DeleteQueue(models.QueueId) + DeleteQueue(models.QueueId) (*mongo.DeleteResult, 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 57b7f8e..e585215 100644 --- a/internal/handler/queue.go +++ b/internal/handler/queue.go @@ -95,12 +95,20 @@ func ResumeQueue(w http.ResponseWriter, r *http.Request) { func DeleteQueue(w http.ResponseWriter, r *http.Request) { id := r.Context().Value("id").(string) if id == "" { - w.WriteHeader(http.StatusNotFound) + http.Error(w, fmt.Sprintf("Invalid Id: %s", id), 404) + return + } + result, err := datastore.Store.DeleteQueue(models.QueueId(id)) + if err != nil { + http.Error(w, fmt.Sprint(err), 400) return } - log.Println("URL path param 'id' is: " + string(id)) - datastore.Store.DeleteQueue(models.QueueId(id)) - fmt.Fprintf(w, "Delete queue") + if result.DeletedCount == 0 { + http.Error(w, fmt.Sprintf("No record found for Queue Id: %s", id), 404) + return + } + fmt.Fprintf(w, "Deleted Queue Id: %s", id) + w.WriteHeader(200) } func QueueCtx(next http.Handler) http.Handler { From 1e0293df9b80943b4edfaa87919df89ea815c74a Mon Sep 17 00:00:00 2001 From: Sijin Pavithran Date: Tue, 11 Jan 2022 23:35:52 +0000 Subject: [PATCH 07/10] Added error handling to create queue --- internal/datastore/mongo_store.go | 6 +++--- internal/datastore/store.go | 2 +- internal/handler/queue.go | 16 ++++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/internal/datastore/mongo_store.go b/internal/datastore/mongo_store.go index f44229a..d53ac7c 100644 --- a/internal/datastore/mongo_store.go +++ b/internal/datastore/mongo_store.go @@ -47,19 +47,19 @@ 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(id models.QueueId) (models.Queue, error) { diff --git a/internal/datastore/store.go b/internal/datastore/store.go index 3ed499b..fea585f 100644 --- a/internal/datastore/store.go +++ b/internal/datastore/store.go @@ -7,7 +7,7 @@ import ( 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, error) diff --git a/internal/handler/queue.go b/internal/handler/queue.go index e585215..ebe47a2 100644 --- a/internal/handler/queue.go +++ b/internal/handler/queue.go @@ -34,7 +34,7 @@ func CreateQueue(w http.ResponseWriter, r *http.Request) { err := decoder.Decode(&q) if err != nil { - panic(err) + http.Error(w, fmt.Sprint(err), 400) } // Initialize values @@ -44,14 +44,14 @@ 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 := datastore.Store.CreateQueue(q) - + insertedId, err := datastore.Store.CreateQueue(q) + if err != nil { + http.Error(w, fmt.Sprint(err), 400) + return + } log.Printf("Inserted %s", insertedId) - - fmt.Fprintf(w, "Post queue") + w.WriteHeader(201) + fmt.Fprintf(w, "Queue created with Id: %s", insertedId) } func PauseQueue(w http.ResponseWriter, r *http.Request) { From c15de67e16d9ced74d3e685a6c5c702762258d7a Mon Sep 17 00:00:00 2001 From: Sijin Pavithran Date: Tue, 11 Jan 2022 23:35:52 +0000 Subject: [PATCH 08/10] Added error handling to create queue --- internal/datastore/mongo_store.go | 8 ++++---- internal/datastore/store.go | 2 +- internal/handler/queue.go | 16 ++++++++-------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/internal/datastore/mongo_store.go b/internal/datastore/mongo_store.go index f44229a..320e408 100644 --- a/internal/datastore/mongo_store.go +++ b/internal/datastore/mongo_store.go @@ -47,19 +47,19 @@ 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(id models.QueueId) (models.Queue, error) { @@ -83,7 +83,7 @@ func (mongodb MongoDB) SetIsPaused(id models.QueueId, isPaused bool) (*mongo.Upd context.TODO(), bson.M{"_id": queueId}, bson.D{ - {"$set", bson.D{{"isPaused", isPaused}}}, + {Key: "$set", Value: bson.D{primitive.E{Key: "isPaused", Value: isPaused}}}, }, ) diff --git a/internal/datastore/store.go b/internal/datastore/store.go index 3ed499b..fea585f 100644 --- a/internal/datastore/store.go +++ b/internal/datastore/store.go @@ -7,7 +7,7 @@ import ( 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, error) diff --git a/internal/handler/queue.go b/internal/handler/queue.go index e585215..ebe47a2 100644 --- a/internal/handler/queue.go +++ b/internal/handler/queue.go @@ -34,7 +34,7 @@ func CreateQueue(w http.ResponseWriter, r *http.Request) { err := decoder.Decode(&q) if err != nil { - panic(err) + http.Error(w, fmt.Sprint(err), 400) } // Initialize values @@ -44,14 +44,14 @@ 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 := datastore.Store.CreateQueue(q) - + insertedId, err := datastore.Store.CreateQueue(q) + if err != nil { + http.Error(w, fmt.Sprint(err), 400) + return + } log.Printf("Inserted %s", insertedId) - - fmt.Fprintf(w, "Post queue") + w.WriteHeader(201) + fmt.Fprintf(w, "Queue created with Id: %s", insertedId) } func PauseQueue(w http.ResponseWriter, r *http.Request) { From 5e97fa7591e57d631c6aefc4af9672e6d982e2a2 Mon Sep 17 00:00:00 2001 From: Sijin Pavithran Date: Sun, 30 Jan 2022 01:00:57 +0000 Subject: [PATCH 09/10] Replaced status codes with constants from http package --- internal/handler/queue.go | 48 +++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/internal/handler/queue.go b/internal/handler/queue.go index ebe47a2..778bcbb 100644 --- a/internal/handler/queue.go +++ b/internal/handler/queue.go @@ -13,15 +13,19 @@ import ( "github.com/go-chi/chi/v5" ) +type key int + +const queueId key = 0 + func GetQueue(w http.ResponseWriter, r *http.Request) { - id := r.Context().Value("id").(string) + id := r.Context().Value(queueId).(string) if id == "" { - http.Error(w, fmt.Sprintf("Invalid Id: %s", id), 404) + http.Error(w, fmt.Sprintf("Invalid Id: %s", id), http.StatusNotFound) return } queue, err := datastore.Store.ReadQueue(models.QueueId(id)) if err != nil { - http.Error(w, fmt.Sprintf("No record found for Queue Id: %s", id), 404) + http.Error(w, fmt.Sprintf("No record found for Queue Id: %s", id), http.StatusNotFound) return } json.NewEncoder(w).Encode(queue) @@ -34,7 +38,7 @@ func CreateQueue(w http.ResponseWriter, r *http.Request) { err := decoder.Decode(&q) if err != nil { - http.Error(w, fmt.Sprint(err), 400) + http.Error(w, fmt.Sprint(err), http.StatusBadRequest) } // Initialize values @@ -46,74 +50,74 @@ func CreateQueue(w http.ResponseWriter, r *http.Request) { insertedId, err := datastore.Store.CreateQueue(q) if err != nil { - http.Error(w, fmt.Sprint(err), 400) + http.Error(w, fmt.Sprint(err), http.StatusBadRequest) return } log.Printf("Inserted %s", insertedId) - w.WriteHeader(201) + w.WriteHeader(http.StatusCreated) fmt.Fprintf(w, "Queue created with Id: %s", insertedId) } func PauseQueue(w http.ResponseWriter, r *http.Request) { - id := r.Context().Value("id").(string) + id := r.Context().Value(queueId).(string) if id == "" { - http.Error(w, fmt.Sprintf("Invalid Id: %s", id), 404) + http.Error(w, fmt.Sprintf("Invalid Id: %s", id), http.StatusNotFound) return } result, err := datastore.Store.SetIsPaused(models.QueueId(id), true) // Set IsPaused = true if err != nil { - http.Error(w, fmt.Sprint(err), 400) + http.Error(w, fmt.Sprint(err), http.StatusBadRequest) return } if result.ModifiedCount == 0 { - http.Error(w, fmt.Sprintf("No record found for Queue Id: %s", id), 404) + http.Error(w, fmt.Sprintf("No record found for Queue Id: %s", id), http.StatusNotFound) return } fmt.Fprintf(w, "Paused Queue Id: %s", id) - w.WriteHeader(200) + w.WriteHeader(http.StatusOK) } func ResumeQueue(w http.ResponseWriter, r *http.Request) { - id := r.Context().Value("id").(string) + id := r.Context().Value(queueId).(string) if id == "" { - http.Error(w, fmt.Sprintf("Invalid Id: %s", id), 404) + http.Error(w, fmt.Sprintf("Invalid Id: %s", id), http.StatusNotFound) return } result, err := datastore.Store.SetIsPaused(models.QueueId(id), false) // Set IsPaused = false if err != nil { - http.Error(w, fmt.Sprint(err), 400) + http.Error(w, fmt.Sprint(err), http.StatusBadRequest) return } if result.ModifiedCount == 0 { - http.Error(w, fmt.Sprintf("No record found for Queue Id: %s", id), 404) + http.Error(w, fmt.Sprintf("No record found for Queue Id: %s", id), http.StatusNotFound) return } fmt.Fprintf(w, "Resumed Queue Id: %s", id) - w.WriteHeader(200) + w.WriteHeader(http.StatusOK) } func DeleteQueue(w http.ResponseWriter, r *http.Request) { - id := r.Context().Value("id").(string) + id := r.Context().Value(queueId).(string) if id == "" { - http.Error(w, fmt.Sprintf("Invalid Id: %s", id), 404) + http.Error(w, fmt.Sprintf("Invalid Id: %s", id), http.StatusNotFound) return } result, err := datastore.Store.DeleteQueue(models.QueueId(id)) if err != nil { - http.Error(w, fmt.Sprint(err), 400) + http.Error(w, fmt.Sprint(err), http.StatusBadRequest) return } if result.DeletedCount == 0 { - http.Error(w, fmt.Sprintf("No record found for Queue Id: %s", id), 404) + http.Error(w, fmt.Sprintf("No record found for Queue Id: %s", id), http.StatusNotFound) return } fmt.Fprintf(w, "Deleted Queue Id: %s", id) - w.WriteHeader(200) + w.WriteHeader(http.StatusOK) } func QueueCtx(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := context.WithValue(r.Context(), "id", chi.URLParam(r, "id")) + ctx := context.WithValue(r.Context(), queueId, chi.URLParam(r, "id")) next.ServeHTTP(w, r.WithContext(ctx)) }) } From d38722ce3e6056d5f67b1e12cd0319a05d9c601c Mon Sep 17 00:00:00 2001 From: Sijin Pavithran Date: Sun, 30 Jan 2022 14:06:01 +0000 Subject: [PATCH 10/10] Restructuring QueueStore interface to be database independent --- internal/datastore/mongo_store.go | 24 ++++++++++++++------- internal/datastore/store.go | 5 ++--- internal/handler/queue.go | 36 +++++++++++-------------------- 3 files changed, 30 insertions(+), 35 deletions(-) diff --git a/internal/datastore/mongo_store.go b/internal/datastore/mongo_store.go index 320e408..af88940 100644 --- a/internal/datastore/mongo_store.go +++ b/internal/datastore/mongo_store.go @@ -2,6 +2,7 @@ package datastore import ( "context" + "errors" "log" "os" @@ -77,7 +78,7 @@ func (mongodb MongoDB) ReadQueue(id models.QueueId) (models.Queue, error) { return result, nil } -func (mongodb MongoDB) SetIsPaused(id models.QueueId, isPaused bool) (*mongo.UpdateResult, error) { +func (mongodb MongoDB) SetIsPaused(id models.QueueId, isPaused bool) error { queueId, _ := primitive.ObjectIDFromHex(string(id)) result, err := mongodb.Queue.UpdateOne( context.TODO(), @@ -86,24 +87,31 @@ func (mongodb MongoDB) SetIsPaused(id models.QueueId, isPaused bool) (*mongo.Upd {Key: "$set", Value: bson.D{primitive.E{Key: "isPaused", Value: isPaused}}}, }, ) - if err != nil { - return result, err + return err + } + log.Printf("Records updated:%d", result.ModifiedCount) + if result.ModifiedCount == 0 { + return errors.New("no record found") } + return nil - return result, nil } -func (mongodb MongoDB) DeleteQueue(id models.QueueId) (*mongo.DeleteResult, error) { +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 result, err + return err } - - return result, nil + 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 fea585f..6b37baa 100644 --- a/internal/datastore/store.go +++ b/internal/datastore/store.go @@ -2,7 +2,6 @@ package datastore import ( "github.com/SimplQ/simplQ-golang/internal/models" - "go.mongodb.org/mongo-driver/mongo" ) type QueueStore interface { @@ -13,10 +12,10 @@ type QueueStore interface { ReadQueue(models.QueueId) (models.Queue, error) // Set the queue pause status to true/false - SetIsPaused(models.QueueId, bool) (*mongo.UpdateResult, error) + SetIsPaused(models.QueueId, bool) error // Set the queue delete status to new value. - DeleteQueue(models.QueueId) (*mongo.DeleteResult, error) + 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 778bcbb..62ccf4a 100644 --- a/internal/handler/queue.go +++ b/internal/handler/queue.go @@ -20,12 +20,12 @@ const queueId key = 0 func GetQueue(w http.ResponseWriter, r *http.Request) { id := r.Context().Value(queueId).(string) if id == "" { - http.Error(w, fmt.Sprintf("Invalid Id: %s", id), http.StatusNotFound) + 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.Sprintf("No record found for Queue Id: %s", id), http.StatusNotFound) + http.Error(w, fmt.Sprint(err), http.StatusInternalServerError) return } json.NewEncoder(w).Encode(queue) @@ -50,7 +50,7 @@ func CreateQueue(w http.ResponseWriter, r *http.Request) { insertedId, err := datastore.Store.CreateQueue(q) if err != nil { - http.Error(w, fmt.Sprint(err), http.StatusBadRequest) + http.Error(w, fmt.Sprint(err), http.StatusInternalServerError) return } log.Printf("Inserted %s", insertedId) @@ -61,16 +61,12 @@ func CreateQueue(w http.ResponseWriter, r *http.Request) { 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.StatusNotFound) + http.Error(w, fmt.Sprintf("Invalid Id: %s", id), http.StatusBadRequest) return } - result, err := datastore.Store.SetIsPaused(models.QueueId(id), true) // Set IsPaused = true + err := datastore.Store.SetIsPaused(models.QueueId(id), true) // Set IsPaused = true if err != nil { - http.Error(w, fmt.Sprint(err), http.StatusBadRequest) - return - } - if result.ModifiedCount == 0 { - http.Error(w, fmt.Sprintf("No record found for Queue Id: %s", id), http.StatusNotFound) + http.Error(w, fmt.Sprint(err), http.StatusInternalServerError) return } fmt.Fprintf(w, "Paused Queue Id: %s", id) @@ -80,16 +76,12 @@ func PauseQueue(w http.ResponseWriter, r *http.Request) { 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.StatusNotFound) + http.Error(w, fmt.Sprintf("Invalid Id: %s", id), http.StatusBadRequest) return } - result, err := datastore.Store.SetIsPaused(models.QueueId(id), false) // Set IsPaused = false + err := datastore.Store.SetIsPaused(models.QueueId(id), false) // Set IsPaused = false if err != nil { - http.Error(w, fmt.Sprint(err), http.StatusBadRequest) - return - } - if result.ModifiedCount == 0 { - http.Error(w, fmt.Sprintf("No record found for Queue Id: %s", id), http.StatusNotFound) + http.Error(w, fmt.Sprint(err), http.StatusInternalServerError) return } fmt.Fprintf(w, "Resumed Queue Id: %s", id) @@ -99,16 +91,12 @@ func ResumeQueue(w http.ResponseWriter, r *http.Request) { 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.StatusNotFound) + http.Error(w, fmt.Sprintf("Invalid Id: %s", id), http.StatusBadRequest) return } - result, err := datastore.Store.DeleteQueue(models.QueueId(id)) + err := datastore.Store.DeleteQueue(models.QueueId(id)) if err != nil { - http.Error(w, fmt.Sprint(err), http.StatusBadRequest) - return - } - if result.DeletedCount == 0 { - http.Error(w, fmt.Sprintf("No record found for Queue Id: %s", id), http.StatusNotFound) + http.Error(w, fmt.Sprint(err), http.StatusInternalServerError) return } fmt.Fprintf(w, "Deleted Queue Id: %s", id)