Skip to content

Commit

Permalink
tests: fixing tests on redis server (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipebrsk authored Sep 21, 2024
1 parent cbdb398 commit d5a1795
Show file tree
Hide file tree
Showing 12 changed files with 119 additions and 62 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ jobs:
- name: Execute tests
run: go test ./tests/...

all_required_checks_passed:
name: All required checks passed
runs-on: ubuntu-latest
needs: [tests]
if: contains(github.ref, 'refs/heads/main') != true
steps:
- name: Mark PR as ready to merge
run: exit 0

release:
name: Generate a new release
needs: [tests]
Expand Down
2 changes: 2 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
)

type Config struct {
ENV string
DBHost string
DBPort string
DBUser string
Expand All @@ -35,6 +36,7 @@ func LoadConfig() *Config {
}

return &Config{
ENV: getEnv("ENV", "local"),
DBHost: getEnv("DB_HOST", "localhost"),
DBPort: getEnv("DB_PORT", "3306"),
DBUser: getEnv("DB_USER", "root"),
Expand Down
5 changes: 5 additions & 0 deletions di/di.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package di
import (
"gcstatus/config"
"gcstatus/internal/usecases"
"gcstatus/pkg/cache"
"log"

"gorm.io/driver/mysql"
Expand All @@ -29,6 +30,10 @@ func InitDependencies() (
// Auto-migrate the database
MigrateModels(dbConn)

if cfg.ENV != "testing" {
cache.GlobalCache = cache.NewRedisCache()
}

// Setup dependencies
userService, authService, passwordResetService := Setup(dbConn)

Expand Down
4 changes: 2 additions & 2 deletions internal/adapters/api/auth_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ func (h *AuthHandler) Me(c *gin.Context) {
}

// Try to get the user from the cache
user, found := cache.GetUserFromCache(userID)
user, found := cache.GlobalCache.GetUserFromCache(userID)
if !found {
// If user is not in the cache, retrieve from the service
user, err = h.userService.GetUserByID(userID)
Expand All @@ -255,7 +255,7 @@ func (h *AuthHandler) Me(c *gin.Context) {
return
}
// Store the user in the cache
cache.SetUserInCache(userID, user)
cache.GlobalCache.SetUserInCache(user)
}

transformedUser := resources.TransformUser(*user)
Expand Down
5 changes: 1 addition & 4 deletions internal/adapters/api/password_reset_handler.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package api

import (
"context"
"gcstatus/internal/domain"
"gcstatus/internal/usecases"
"gcstatus/pkg/cache"
Expand Down Expand Up @@ -68,8 +67,6 @@ func (h *PasswordResetHandler) RequestPasswordReset(c *gin.Context) {
}

func (h *PasswordResetHandler) ResetUserPassword(c *gin.Context) {
ctx := context.Background()

var request struct {
Email string `json:"email" binding:"required"`
Password string `json:"password" binding:"required"`
Expand Down Expand Up @@ -131,7 +128,7 @@ func (h *PasswordResetHandler) ResetUserPassword(c *gin.Context) {
return
}

cache.RemovePasswordThrottleCache(ctx, user.Email)
cache.GlobalCache.RemovePasswordThrottleCache(user.Email)

c.JSON(http.StatusOK, gin.H{"message": "You password was successfully reseted!"})
}
7 changes: 2 additions & 5 deletions internal/middlewares/limit_throttle_middleware.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package middlewares

import (
"context"
"gcstatus/pkg/cache"
"log"
"net/http"
Expand All @@ -16,14 +15,12 @@ var (
)

func LimitThrottleMiddleware() gin.HandlerFunc {
var ctx = context.Background()

return func(c *gin.Context) {
ip := c.ClientIP()
key := "rate-limit:" + ip

// Increment the request count and set expiration if not set
count, err := cache.AddThrottleCache(ctx, key)
count, err := cache.GlobalCache.AddThrottleCache(key)
if err != nil {
log.Fatal(err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Internal Server Error"})
Expand All @@ -33,7 +30,7 @@ func LimitThrottleMiddleware() gin.HandlerFunc {

// Set expiration for the key if it's the first request
if count == 1 {
cache.ExpireThrottleCache(ctx, key, TimeWindow)
cache.GlobalCache.ExpireThrottleCache(key, TimeWindow)
}

// Check if the user exceeded the rate limit
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package middlewares

import (
"context"
"gcstatus/pkg/cache"
"net/http"
"time"
Expand All @@ -16,8 +15,6 @@ const (

// LimitResetRequestMiddleware is middleware that allows one request per minute
func LimitResetRequestMiddleware() gin.HandlerFunc {
var ctx = context.Background()

return func(c *gin.Context) {
var input struct {
Email string `json:"email" binding:"required,email"`
Expand All @@ -31,9 +28,9 @@ func LimitResetRequestMiddleware() gin.HandlerFunc {

emailKey := "password-reset:" + input.Email

_, err := cache.GetPasswordThrottleCache(ctx, emailKey)
_, err := cache.GlobalCache.GetPasswordThrottleCache(emailKey)
if err == redis.Nil {
cache.SetPasswordThrottleCache(ctx, emailKey, oneMinute)
cache.GlobalCache.SetPasswordThrottleCache(emailKey, oneMinute)

c.Next()
} else if err != nil {
Expand Down
32 changes: 28 additions & 4 deletions pkg/cache/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,36 @@ package cache
import (
"context"
"gcstatus/config"
"gcstatus/internal/domain"
"time"

"github.com/go-redis/redis/v8"
)

var env = config.LoadConfig()
type Cache interface {
AddThrottleCache(key string) (int64, error)
ExpireThrottleCache(key string, timeWindow time.Duration)
GetPasswordThrottleCache(key string) (string, error)
SetPasswordThrottleCache(key string, duration time.Duration) error
RemovePasswordThrottleCache(email string) error
GetUserFromCache(userID uint) (*domain.User, bool)
SetUserInCache(user *domain.User)
RemoveUserFromCache(userID uint)
}

type RedisCache struct {
client *redis.Client
}

var ctx = context.Background()
var rdb = redis.NewClient(&redis.Options{
Addr: env.RedisHost,
})
var env = config.LoadConfig()

func NewRedisCache() *RedisCache {
rdb := redis.NewClient(&redis.Options{
Addr: env.RedisHost,
})

return &RedisCache{client: rdb}
}

var GlobalCache Cache
13 changes: 6 additions & 7 deletions pkg/cache/limit_throttle_password_request_cache.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
package cache

import (
"context"
"time"
)

func GetPasswordThrottleCache(ctx context.Context, key string) (string, error) {
value, err := rdb.Get(ctx, key).Result()
func (r *RedisCache) GetPasswordThrottleCache(key string) (string, error) {
value, err := r.client.Get(ctx, key).Result()

return value, err
}

func SetPasswordThrottleCache(ctx context.Context, key string, duration time.Duration) error {
_, err := rdb.Set(ctx, key, 1, duration).Result()
func (r *RedisCache) SetPasswordThrottleCache(key string, duration time.Duration) error {
_, err := r.client.Set(ctx, key, 1, duration).Result()

return err
}

func RemovePasswordThrottleCache(ctx context.Context, email string) error {
func (r *RedisCache) RemovePasswordThrottleCache(email string) error {
key := "password-reset:" + email

_, err := rdb.Del(ctx, key).Result()
_, err := r.client.Del(ctx, key).Result()

return err
}
9 changes: 4 additions & 5 deletions pkg/cache/throttle_cache.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package cache

import (
"context"
"time"
)

func AddThrottleCache(ctx context.Context, key string) (count int64, error error) {
count, err := rdb.Incr(ctx, key).Result()
func (r *RedisCache) AddThrottleCache(key string) (count int64, error error) {
count, err := r.client.Incr(ctx, key).Result()

return count, err
}

func ExpireThrottleCache(ctx context.Context, key string, timeWindow time.Duration) {
rdb.Expire(ctx, key, timeWindow)
func (r *RedisCache) ExpireThrottleCache(key string, timeWindow time.Duration) {
r.client.Expire(ctx, key, timeWindow)
}
14 changes: 7 additions & 7 deletions pkg/cache/user_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
"github.com/go-redis/redis/v8"
)

func GetUserFromCache(userID uint) (*domain.User, bool) {
func (r *RedisCache) GetUserFromCache(userID uint) (*domain.User, bool) {
key := fmt.Sprintf("user:%d", userID)
result, err := rdb.Get(ctx, key).Result()
result, err := r.client.Get(ctx, key).Result()
if err != nil {
if err == redis.Nil {
return nil, false
Expand All @@ -28,21 +28,21 @@ func GetUserFromCache(userID uint) (*domain.User, bool) {
return &user, true
}

func SetUserInCache(userID uint, user *domain.User) {
key := fmt.Sprintf("user:%d", userID)
func (r *RedisCache) SetUserInCache(user *domain.User) {
key := fmt.Sprintf("user:%d", user.ID)
data, err := json.Marshal(user)
if err != nil {
log.Println("Marshal error:", err)
return
}
if err := rdb.Set(ctx, key, data, 0).Err(); err != nil {
if err := r.client.Set(ctx, key, data, 0).Err(); err != nil {
log.Println("Redis error:", err)
}
}

func RemoveUserFromCache(userID uint) {
func (r *RedisCache) RemoveUserFromCache(userID uint) {
key := fmt.Sprintf("user:%d", userID)
if err := rdb.Del(ctx, key).Err(); err != nil {
if err := r.client.Del(ctx, key).Err(); err != nil {
log.Println("Redis error:", err)
}
}
Loading

0 comments on commit d5a1795

Please sign in to comment.