Skip to content

Commit 7a048ed

Browse files
committed
feat: caching for show Receipt with Redis
1 parent 6c36b0c commit 7a048ed

File tree

9 files changed

+123
-8
lines changed

9 files changed

+123
-8
lines changed

.env.example

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,8 @@ DB_PASS=test
33
DB_HOST=localhost
44
DB_NAME=golang_api
55

6-
JWT_SECRET=jwtsecret123
6+
JWT_SECRET=jwtsecret123
7+
8+
REDIS_HOST=localhost
9+
REDIS_PORT=6379
10+
REDIS_PASS=""

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
database/
22
portainer-data/
33
.env
4+
redis-data/

cache/receipt-cache.go

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package cache
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"time"
7+
8+
"github.com/go-redis/redis/v8"
9+
"github.com/putukrisna6/golang-api/entity"
10+
)
11+
12+
type ReceiptCache interface {
13+
Set(key string, value entity.Receipt)
14+
Get(key string) entity.Receipt
15+
}
16+
17+
type receiptCache struct {
18+
cache *redis.Client
19+
expires time.Duration
20+
}
21+
22+
func NewReceiptCache(cache *redis.Client, expires time.Duration) ReceiptCache {
23+
return &receiptCache{
24+
cache: cache,
25+
expires: expires,
26+
}
27+
}
28+
29+
func (rc *receiptCache) Set(key string, value entity.Receipt) {
30+
json, err := json.Marshal(value)
31+
if err != nil {
32+
panic(err)
33+
}
34+
35+
rc.cache.Set(context.TODO(), key, json, rc.expires*time.Second)
36+
}
37+
38+
func (rc *receiptCache) Get(key string) entity.Receipt {
39+
val, errGet := rc.cache.Get(context.TODO(), key).Result()
40+
41+
if errGet == redis.Nil {
42+
return entity.Receipt{}
43+
} else if errGet != nil {
44+
panic(errGet)
45+
}
46+
47+
receipt := entity.Receipt{}
48+
err := json.Unmarshal([]byte(val), &receipt)
49+
if err != nil {
50+
panic(err)
51+
}
52+
53+
return receipt
54+
}

config/redis-config.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package config
2+
3+
import (
4+
"os"
5+
6+
"github.com/go-redis/redis/v8"
7+
"github.com/joho/godotenv"
8+
)
9+
10+
func SetupRedisConnection() *redis.Client {
11+
errEnv := godotenv.Load()
12+
13+
if errEnv != nil {
14+
panic("failed to load env")
15+
}
16+
17+
redisPort := os.Getenv("REDIS_PORT")
18+
redisPass := os.Getenv("REDIS_PASS")
19+
redisHost := os.Getenv("REDIS_HOST")
20+
21+
rdb := redis.NewClient(&redis.Options{
22+
Addr: redisHost + ":" + redisPort,
23+
Password: redisPass,
24+
DB: 0, // use default DB
25+
})
26+
27+
return rdb
28+
}

controller/receipt-controller.go

+12-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"strconv"
77

88
"github.com/gin-gonic/gin"
9+
"github.com/putukrisna6/golang-api/cache"
910
"github.com/putukrisna6/golang-api/dto"
1011
"github.com/putukrisna6/golang-api/entity"
1112
"github.com/putukrisna6/golang-api/helper"
@@ -22,11 +23,13 @@ type ReceiptController interface {
2223

2324
type receiptController struct {
2425
receiptService service.ReceiptService
26+
receiptCache cache.ReceiptCache
2527
}
2628

27-
func NewReceiptController(receiptService service.ReceiptService) ReceiptController {
29+
func NewReceiptController(receiptService service.ReceiptService, receiptCache cache.ReceiptCache) ReceiptController {
2830
return &receiptController{
2931
receiptService: receiptService,
32+
receiptCache: receiptCache,
3033
}
3134
}
3235

@@ -44,11 +47,15 @@ func (c *receiptController) Show(context *gin.Context) {
4447
return
4548
}
4649

47-
var receipt entity.Receipt = c.receiptService.Show(id)
50+
var receipt entity.Receipt = c.receiptCache.Get(strconv.FormatUint(id, 10))
4851
if (receipt == entity.Receipt{}) {
49-
res := helper.BuildErrorResponse("failed to retrieve Receipt", "no data with given receiptID", helper.EmptyObj{})
50-
context.AbortWithStatusJSON(http.StatusNotFound, res)
51-
return
52+
var receipt entity.Receipt = c.receiptService.Show(id)
53+
if (receipt == entity.Receipt{}) {
54+
res := helper.BuildErrorResponse("failed to retrieve Receipt", "no data with given receiptID", helper.EmptyObj{})
55+
context.AbortWithStatusJSON(http.StatusNotFound, res)
56+
return
57+
}
58+
c.receiptCache.Set(strconv.FormatUint(id, 10), receipt)
5259
}
5360

5461
res := helper.BuildValidResponse("OK", receipt)

docker-compose.yml

+8-1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,11 @@ services:
3131
- /var/run/docker.sock:/var/run/docker.sock:ro
3232
- ./portainer-data:/data
3333
ports:
34-
- 9000:9000
34+
- 9000:9000
35+
cache:
36+
image: redis:alpine
37+
restart: always
38+
volumes:
39+
- ./redis-data:/data
40+
ports:
41+
- 6379:6379

go.mod

+3
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@ require (
1414
)
1515

1616
require (
17+
github.com/cespare/xxhash/v2 v2.1.2 // indirect
18+
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
1719
github.com/gin-contrib/sse v0.1.0 // indirect
1820
github.com/go-playground/locales v0.14.0 // indirect
1921
github.com/go-playground/universal-translator v0.18.0 // indirect
2022
github.com/go-playground/validator/v10 v10.10.1 // indirect
23+
github.com/go-redis/redis/v8 v8.11.5 // indirect
2124
github.com/go-sql-driver/mysql v1.6.0 // indirect
2225
github.com/golang/protobuf v1.5.2 // indirect
2326
github.com/jinzhu/inflection v1.0.0 // indirect

go.sum

+6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
2+
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
13
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
24
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
35
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
46
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
57
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
68
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
9+
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
10+
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
711
github.com/gin-contrib/cors v1.3.1 h1:doAsuITavI4IOcd0Y19U4B+O0dNWihRyX//nn4sEmgA=
812
github.com/gin-contrib/cors v1.3.1/go.mod h1:jjEJ4268OPZUcU7k9Pm653S7lXUGcqMADzFA61xsmDk=
913
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
@@ -24,6 +28,8 @@ github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl
2428
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
2529
github.com/go-playground/validator/v10 v10.10.1 h1:uA0+amWMiglNZKZ9FJRKUAe9U3RX91eVn1JYXMWt7ig=
2630
github.com/go-playground/validator/v10 v10.10.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
31+
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
32+
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
2733
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
2834
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
2935
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=

server.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package main
33
import (
44
"github.com/gin-contrib/cors"
55
"github.com/gin-gonic/gin"
6+
"github.com/go-redis/redis/v8"
7+
"github.com/putukrisna6/golang-api/cache"
68
"github.com/putukrisna6/golang-api/config"
79
"github.com/putukrisna6/golang-api/controller"
810
"github.com/putukrisna6/golang-api/middleware"
@@ -17,6 +19,9 @@ var (
1719
bookRepository repository.BookRepository = repository.NewBookRepository(db)
1820
receiptRepository repository.ReceiptRepository = repository.NewReceiptRepository(db)
1921

22+
rd *redis.Client = config.SetupRedisConnection()
23+
receiptCache cache.ReceiptCache = cache.NewReceiptCache(rd, 1000) // random expiration lmao
24+
2025
jwtService service.JWTService = service.NewJWTService()
2126
authService service.AuthService = service.NewAuthService(userRepository)
2227
userService service.UserService = service.NewUserService(userRepository)
@@ -26,7 +31,7 @@ var (
2631
authController controller.AuthController = controller.NewAuthController(authService, jwtService)
2732
userController controller.UserController = controller.NewUserController(userService, jwtService)
2833
bookController controller.BookController = controller.NewBookController(bookService, jwtService)
29-
receiptController controller.ReceiptController = controller.NewReceiptController(receiptService)
34+
receiptController controller.ReceiptController = controller.NewReceiptController(receiptService, receiptCache)
3035
)
3136

3237
func main() {

0 commit comments

Comments
 (0)