11package api
22
33import (
4+ "context"
45 "encoding/json"
6+ "golang-rest-api-template/pkg/cache"
7+ "golang-rest-api-template/pkg/database"
58 "golang-rest-api-template/pkg/models"
69 "net/http"
710 "strconv"
@@ -10,6 +13,31 @@ import (
1013 "github.com/gin-gonic/gin"
1114)
1215
16+ type BookRepository interface {
17+ Healthcheck (c * gin.Context )
18+ FindBooks (c * gin.Context )
19+ CreateBook (c * gin.Context )
20+ FindBook (c * gin.Context )
21+ UpdateBook (c * gin.Context )
22+ DeleteBook (c * gin.Context )
23+ }
24+
25+ // bookRepository holds shared resources like database and Redis client
26+ type bookRepository struct {
27+ DB database.Database
28+ RedisClient cache.Cache
29+ Ctx * context.Context
30+ }
31+
32+ // NewAppContext creates a new AppContext
33+ func NewBookRepository (db database.Database , redisClient cache.Cache , ctx * context.Context ) * bookRepository {
34+ return & bookRepository {
35+ DB : db ,
36+ RedisClient : redisClient ,
37+ Ctx : ctx ,
38+ }
39+ }
40+
1341// @BasePath /api/v1
1442
1543// Healthcheck godoc
@@ -21,8 +49,8 @@ import (
2149// @Produce json
2250// @Success 200 {string} ok
2351// @Router / [get]
24- func Healthcheck (g * gin.Context ) {
25- g .JSON (http .StatusOK , "ok" )
52+ func ( r * bookRepository ) Healthcheck (c * gin.Context ) {
53+ c .JSON (http .StatusOK , "ok" )
2654}
2755
2856// FindBooks godoc
@@ -35,13 +63,7 @@ func Healthcheck(g *gin.Context) {
3563// @Param limit query int false "Limit for pagination" default(10)
3664// @Success 200 {array} models.Book "Successfully retrieved list of books"
3765// @Router /books [get]
38- func FindBooks (c * gin.Context ) {
39- appCtx , exists := c .MustGet ("appCtx" ).(* AppContext )
40- if ! exists {
41- c .JSON (http .StatusInternalServerError , gin.H {"error" : "internal server error" })
42- return
43- }
44-
66+ func (r * bookRepository ) FindBooks (c * gin.Context ) {
4567 var books []models.Book
4668
4769 // Get query params
@@ -65,7 +87,7 @@ func FindBooks(c *gin.Context) {
6587 cacheKey := "books_offset_" + offsetQuery + "_limit_" + limitQuery
6688
6789 // Try fetching the data from Redis first
68- cachedBooks , err := appCtx .RedisClient .Get (* appCtx .Ctx , cacheKey ).Result ()
90+ cachedBooks , err := r .RedisClient .Get (* r .Ctx , cacheKey ).Result ()
6991 if err == nil {
7092 err := json .Unmarshal ([]byte (cachedBooks ), & books )
7193 if err != nil {
@@ -77,15 +99,15 @@ func FindBooks(c *gin.Context) {
7799 }
78100
79101 // If cache missed, fetch data from the database
80- appCtx .DB .Offset (offset ).Limit (limit ).Find (& books )
102+ r .DB .Offset (offset ).Limit (limit ).Find (& books )
81103
82104 // Serialize books object and store it in Redis
83105 serializedBooks , err := json .Marshal (books )
84106 if err != nil {
85107 c .JSON (http .StatusInternalServerError , gin.H {"error" : "Failed to marshal data" })
86108 return
87109 }
88- err = appCtx .RedisClient .Set (* appCtx .Ctx , cacheKey , serializedBooks , time .Minute ).Err () // Here TTL is set to one hour
110+ err = r .RedisClient .Set (* r .Ctx , cacheKey , serializedBooks , time .Minute ).Err () // Here TTL is set to one hour
89111 if err != nil {
90112 c .JSON (http .StatusInternalServerError , gin.H {"error" : "Failed to set cache" })
91113 return
@@ -107,8 +129,8 @@ func FindBooks(c *gin.Context) {
107129// @Failure 400 {string} string "Bad Request"
108130// @Failure 401 {string} string "Unauthorized"
109131// @Router /books [post]
110- func CreateBook (c * gin.Context ) {
111- appCtx , exists := c .MustGet ("appCtx" ).(* AppContext )
132+ func ( r * bookRepository ) CreateBook (c * gin.Context ) {
133+ appCtx , exists := c .MustGet ("appCtx" ).(* bookRepository )
112134 if ! exists {
113135 c .JSON (http .StatusInternalServerError , gin.H {"error" : "internal server error" })
114136 return
@@ -146,15 +168,10 @@ func CreateBook(c *gin.Context) {
146168// @Success 200 {object} models.Book "Successfully retrieved book"
147169// @Failure 404 {string} string "Book not found"
148170// @Router /books/{id} [get]
149- func FindBook (c * gin.Context ) {
150- appCtx , exists := c .MustGet ("appCtx" ).(* AppContext )
151- if ! exists {
152- c .JSON (http .StatusInternalServerError , gin.H {"error" : "internal server error" })
153- return
154- }
171+ func (r * bookRepository ) FindBook (c * gin.Context ) {
155172 var book models.Book
156173
157- if err := appCtx .DB .Where ("id = ?" , c .Param ("id" )).First (& book ).Error ; err != nil {
174+ if err := r .DB .Where ("id = ?" , c .Param ("id" )).First (& book ).Error ; err != nil {
158175 c .JSON (http .StatusNotFound , gin.H {"error" : "book not found" })
159176 return
160177 }
@@ -175,16 +192,11 @@ func FindBook(c *gin.Context) {
175192// @Failure 400 {string} string "Bad Request"
176193// @Failure 404 {string} string "book not found"
177194// @Router /books/{id} [put]
178- func UpdateBook (c * gin.Context ) {
179- appCtx , exists := c .MustGet ("appCtx" ).(* AppContext )
180- if ! exists {
181- c .JSON (http .StatusInternalServerError , gin.H {"error" : "internal server error" })
182- return
183- }
195+ func (r * bookRepository ) UpdateBook (c * gin.Context ) {
184196 var book models.Book
185197 var input models.UpdateBook
186198
187- if err := appCtx .DB .Where ("id = ?" , c .Param ("id" )).First (& book ).Error ; err != nil {
199+ if err := r .DB .Where ("id = ?" , c .Param ("id" )).First (& book ).Error ; err != nil {
188200 c .JSON (http .StatusNotFound , gin.H {"error" : "book not found" })
189201 return
190202 }
@@ -194,7 +206,7 @@ func UpdateBook(c *gin.Context) {
194206 return
195207 }
196208
197- appCtx .DB .Model (& book ).Updates (models.Book {Title : input .Title , Author : input .Author })
209+ r .DB .Model (& book ).Updates (models.Book {Title : input .Title , Author : input .Author })
198210
199211 c .JSON (http .StatusOK , gin.H {"data" : book })
200212}
@@ -209,8 +221,8 @@ func UpdateBook(c *gin.Context) {
209221// @Success 204 {string} string "Successfully deleted book"
210222// @Failure 404 {string} string "book not found"
211223// @Router /books/{id} [delete]
212- func DeleteBook (c * gin.Context ) {
213- appCtx , exists := c .MustGet ("appCtx" ).(* AppContext )
224+ func ( r * bookRepository ) DeleteBook (c * gin.Context ) {
225+ appCtx , exists := c .MustGet ("appCtx" ).(* bookRepository )
214226 if ! exists {
215227 c .JSON (http .StatusInternalServerError , gin.H {"error" : "internal server error" })
216228 return
0 commit comments