Skip to content

Commit db24078

Browse files
authored
Merge pull request #33 from igh9410/dev
Implementing User matching queue
2 parents 80e168a + 90b7ea3 commit db24078

File tree

16 files changed

+211
-6
lines changed

16 files changed

+211
-6
lines changed

backend/cmd/main.go

+21-3
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ package main
22

33
import (
44
"backend/db"
5+
"backend/infra/kafka"
6+
"backend/infra/redis"
57
"backend/internal/chat"
8+
"backend/internal/match"
69
"backend/internal/user"
7-
"backend/kafka"
810
"backend/router"
911
"log"
12+
"log/slog"
1013
"os"
1114
"strconv"
1215

@@ -17,7 +20,7 @@ import (
1720

1821
func main() {
1922
if err := godotenv.Load("../.env"); err != nil { // Running in local, must be run on go run . in ./cmd directory
20-
log.Println("No .env file found. Using OS environment variables.")
23+
slog.Info("No .env file found. Using OS environment variables.")
2124
}
2225

2326
dbConn, err := db.NewDatabase()
@@ -30,7 +33,17 @@ func main() {
3033
log.Printf("Error closing the database: %s", err)
3134
}
3235
}()
33-
log.Println("Database initialized")
36+
37+
redisClient, err := redis.NewRedisClient()
38+
if err != nil {
39+
log.Fatalf("Could not initialize Redis connection: %s", err)
40+
}
41+
42+
defer func() {
43+
if err := redisClient.Close(); err != nil {
44+
log.Printf("Error closing the Redis connection: %s", err)
45+
}
46+
}()
3447

3548
kafkaClient, err := kafka.NewKafkaClient()
3649
if err != nil {
@@ -58,6 +71,10 @@ func main() {
5871

5972
chatWsHandler := chat.NewWsHandler(hub, chatSvc, kafkaProducer)
6073

74+
matchRep := match.NewRepository(redisClient)
75+
matchSvc := match.NewService(matchRep)
76+
matchHandler := match.NewHandler(matchSvc)
77+
6178
// Create an insert function with the database connection
6279
insertFunc := kafka.NewInsertFunc(dbConn.GetDB())
6380

@@ -86,6 +103,7 @@ func main() {
86103
UserHandler: userHandler,
87104
ChatHandler: chatHandler,
88105
ChatWsHandler: chatWsHandler,
106+
MatchHandler: matchHandler,
89107
// Future handlers can be added here without changing the InitRouter signature
90108
}
91109

backend/db/db.go

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package db
33
import (
44
"database/sql"
55
"fmt"
6+
"log"
67
"os"
78

89
_ "github.com/jackc/pgx/v4/stdlib"
@@ -46,6 +47,7 @@ func NewDatabase() (*Database, error) {
4647
if err != nil {
4748
return nil, err
4849
}
50+
log.Println("Database initialized")
4951

5052
return &Database{db: db}, nil
5153
}

backend/docker-compose.yml

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ services:
1313
env_file:
1414
- ./.env.docker
1515
environment:
16+
- REDIS_URL=redis:6379
1617
- KAFKA_BROKER_URL=broker:9092
1718
- TZ=Asia/Seoul
1819
networks:

backend/go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ require (
4545
github.com/modern-go/reflect2 v1.0.2 // indirect
4646
github.com/pelletier/go-toml/v2 v2.0.9 // indirect
4747
github.com/pmezard/go-difflib v1.0.0 // indirect
48+
github.com/redis/go-redis/v9 v9.3.0 // indirect
4849
github.com/stretchr/objx v0.5.0 // indirect
4950
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
5051
github.com/ugorji/go/codec v1.2.11 // indirect

backend/go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -1558,6 +1558,8 @@ github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
15581558
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
15591559
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
15601560
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
1561+
github.com/redis/go-redis/v9 v9.3.0 h1:RiVDjmig62jIWp7Kk4XVLs0hzV6pI3PyTnnL0cnn0u0=
1562+
github.com/redis/go-redis/v9 v9.3.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
15611563
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
15621564
github.com/rogpeppe/clock v0.0.0-20190514195947-2896927a307a/go.mod h1:4r5QyqhjIWCcK8DO4KMclc5Iknq5qVBAlbYYzAbUScQ=
15631565
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
File renamed without changes.
File renamed without changes.

backend/infra/redis/redis.go

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package redis
2+
3+
import (
4+
"context"
5+
"log"
6+
"os"
7+
8+
"github.com/redis/go-redis/v9"
9+
)
10+
11+
type RedisClient struct {
12+
*redis.Client
13+
}
14+
15+
func NewRedisClient() (*RedisClient, error) {
16+
rdb := redis.NewClient(&redis.Options{
17+
Addr: os.Getenv(("REDIS_URL")),
18+
Password: os.Getenv("REDIS_PASSWORD"), // no password set for local
19+
DB: 0, // use default DB
20+
})
21+
22+
// Create a background context for the Ping operation
23+
ctx := context.Background()
24+
25+
// Ping the Redis server to check for a successful connection
26+
_, err := rdb.Ping(ctx).Result()
27+
if err != nil {
28+
log.Printf("Failed to ping Redis server: %s\n", err)
29+
return nil, err
30+
}
31+
log.Println("Redis initialized")
32+
return &RedisClient{Client: rdb}, nil
33+
}
34+
35+
func (r *RedisClient) Close() error {
36+
return r.Client.Close()
37+
}

backend/internal/chat/handler.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func (h *Handler) JoinChatRoom(c *gin.Context) {
6969
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("Error with joining the chatroom with ID %s and user with ID %s", chatRoomID, userID)})
7070
return
7171
}
72-
c.JSON(http.StatusOK, res)
72+
c.JSON(http.StatusCreated, res)
7373

7474
}
7575

backend/internal/match/handler.go

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package match
2+
3+
import (
4+
"backend/internal/common"
5+
"log"
6+
"log/slog"
7+
"net/http"
8+
9+
"github.com/gin-gonic/gin"
10+
)
11+
12+
type Handler struct {
13+
Service
14+
}
15+
16+
func NewHandler(s Service) *Handler {
17+
return &Handler{
18+
Service: s,
19+
}
20+
}
21+
22+
func (h *Handler) EnqueUser(c *gin.Context) {
23+
// Extract UserID from the context
24+
userID, err := common.UserIDValidator(c.MustGet("user_id"))
25+
if err != nil {
26+
log.Printf("Error occured with user ID %v: %v", userID, err.Error())
27+
}
28+
29+
res, err := h.Service.EnqueUser(c.Request.Context(), userID)
30+
31+
if err != nil {
32+
slog.Error("Error occured with enqueuing user ID %v: %v", userID, err.Error())
33+
}
34+
35+
c.JSON(http.StatusCreated, res)
36+
}

backend/internal/match/model.go

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package match
2+
3+
import (
4+
"time"
5+
6+
"github.com/google/uuid"
7+
)
8+
9+
type EnqueUserRes struct {
10+
ID uuid.UUID `json:"user_id"`
11+
Timestamp time.Time `json:"timestamp"`
12+
}

backend/internal/match/repository.go

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package match
2+
3+
import (
4+
"backend/infra/redis"
5+
"context"
6+
"time"
7+
8+
"github.com/google/uuid"
9+
)
10+
11+
type Repository interface {
12+
EnqueUser(ctx context.Context, userID uuid.UUID) (*EnqueUserRes, error)
13+
}
14+
15+
type repository struct {
16+
redisClient *redis.RedisClient
17+
}
18+
19+
func NewRepository(redisClient *redis.RedisClient) Repository {
20+
return &repository{
21+
redisClient: redisClient,
22+
}
23+
}
24+
25+
func (r *repository) EnqueUser(ctx context.Context, userID uuid.UUID) (*EnqueUserRes, error) {
26+
// Assuming "match_queue" is the Redis key for the matchmaking queue
27+
err := r.redisClient.LPush(ctx, "match_queue", userID.String()).Err()
28+
if err != nil {
29+
return nil, err
30+
}
31+
32+
return &EnqueUserRes{
33+
ID: userID,
34+
Timestamp: time.Now(),
35+
}, nil
36+
}

backend/internal/match/service.go

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package match
2+
3+
import (
4+
"context"
5+
"log/slog"
6+
"time"
7+
8+
"github.com/google/uuid"
9+
)
10+
11+
type Service interface {
12+
EnqueUser(ctx context.Context, userID uuid.UUID) (*EnqueUserRes, error)
13+
}
14+
15+
type service struct {
16+
Repository
17+
timeout time.Duration
18+
}
19+
20+
func NewService(repository Repository) Service {
21+
return &service{
22+
repository,
23+
time.Duration(2) * time.Second,
24+
}
25+
}
26+
27+
func (s *service) EnqueUser(c context.Context, userID uuid.UUID) (*EnqueUserRes, error) {
28+
29+
ctx, cancel := context.WithTimeout(c, s.timeout)
30+
defer cancel()
31+
32+
r, err := s.Repository.EnqueUser(ctx, userID)
33+
34+
if err != nil {
35+
slog.Error("Error enqueuing user:", err)
36+
return nil, err
37+
}
38+
39+
res := &EnqueUserRes{
40+
ID: r.ID,
41+
Timestamp: r.Timestamp,
42+
}
43+
44+
return res, nil
45+
46+
}

backend/internal/user/service.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package user
33
import (
44
"context"
55
"database/sql"
6-
"log"
6+
"log/slog"
77
"time"
88

99
"github.com/google/uuid"
@@ -41,6 +41,7 @@ func (s *service) CreateUser(c context.Context, req *CreateUserReq, userID uuid.
4141

4242
r, err := s.Repository.CreateUser(ctx, u)
4343
if err != nil {
44+
slog.Error("Error creating user:", err)
4445
return nil, err
4546
}
4647

@@ -56,6 +57,7 @@ func (s *service) CreateUser(c context.Context, req *CreateUserReq, userID uuid.
5657
func (s *service) IsUserRegistered(c context.Context, email string) (bool, error) {
5758
_, err := s.Repository.FindUserByEmail(c, email)
5859
if err == sql.ErrNoRows {
60+
slog.Info("User not found with email %v: %v", email, err.Error())
5961
return false, nil
6062
} else if err != nil {
6163
return false, err
@@ -66,7 +68,7 @@ func (s *service) IsUserRegistered(c context.Context, email string) (bool, error
6668
func (s *service) FindUserByEmail(c context.Context, email string) (*UserDTO, error) {
6769
u, err := s.Repository.FindUserByEmail(c, email)
6870
if err != nil {
69-
log.Printf("Error occured with finding user by email %v: %v", email, err.Error())
71+
slog.Error("Error occured with finding user by email %v: %v", email, err.Error())
7072
return nil, err
7173
}
7274
r := &UserDTO{

backend/router/router.go

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"backend/api/middleware"
55

66
"backend/internal/chat"
7+
"backend/internal/match"
78
"backend/internal/user"
89
"context"
910
"log"
@@ -27,6 +28,7 @@ type RouterConfig struct {
2728
UserHandler *user.Handler
2829
ChatHandler *chat.Handler
2930
ChatWsHandler *chat.WsHandler
31+
MatchHandler *match.Handler
3032
// Add future handlers here, e.g.:
3133
// FriendHandler *friend.Handler
3234
}
@@ -81,6 +83,15 @@ func InitRouter(cfg *RouterConfig) {
8183
// etc...
8284
}
8385

86+
matchRoutes := r.Group("/api/matches")
87+
matchRoutes.Use(middleware.EnsureValidToken())
88+
{
89+
// Define your routes here, e.g.
90+
matchRoutes.POST("/", cfg.MatchHandler.EnqueUser)
91+
92+
// etc...
93+
}
94+
8495
// WebSocket api endpoints
8596

8697
chatWsRoutes := r.Group("/ws/chats")

frontend/src/features/user/api/userApi.ts

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export async function fetchUserFn(): Promise<User | null> {
2323
Authorization: `Bearer ${accessToken}`,
2424
},
2525
});
26+
2627
return response.data;
2728
} catch (error) {
2829
if (axios.isAxiosError(error)) {

0 commit comments

Comments
 (0)