Skip to content

Commit 4188b29

Browse files
authored
Merge pull request #1 from WarpWing/patch-1
feat(dev): added conn pool with sync.RWMutex
2 parents a409e9a + a45798f commit 4188b29

File tree

1 file changed

+82
-25
lines changed

1 file changed

+82
-25
lines changed

src/db/redis.go

Lines changed: 82 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package redis
33
import (
44
"context"
55
"fmt"
6+
"os"
7+
"sync"
68
"time"
79

810
"github.com/go-redis/redis/v8"
@@ -13,29 +15,50 @@ var redisClient *redis.Client
1315
var redisAddr string
1416
var redisPassword string
1517
var redisDB int
18+
var clientMutex sync.RWMutex
1619

1720
type RedisClient struct {
1821
client *redis.Client
1922
}
2023

2124
func InitRedis(addr string, password string, db int) error {
25+
clientMutex.Lock()
26+
defer clientMutex.Unlock()
27+
2228
redisAddr = addr
2329
redisPassword = password
2430
redisDB = db
2531

2632
// Don't use sync.Once with prefork mode - each process needs its own connection
2733
redisClient = redis.NewClient(&redis.Options{
28-
Addr: addr,
29-
Password: password,
30-
DB: db,
34+
Addr: addr,
35+
Password: password,
36+
DB: db,
37+
PoolSize: 10,
38+
MinIdleConns: 5,
39+
MaxRetries: 3,
40+
PoolTimeout: time.Second * 4,
41+
IdleTimeout: time.Minute * 5,
42+
DialTimeout: time.Second * 5,
43+
ReadTimeout: time.Second * 3,
44+
WriteTimeout: time.Second * 3,
45+
PoolFIFO: false,
3146
})
3247

33-
_, err := redisClient.Ping(ctx).Result()
48+
ctxTimeout, cancel := context.WithTimeout(ctx, time.Second*5)
49+
defer cancel()
50+
51+
_, err := redisClient.Ping(ctxTimeout).Result()
3452
if err != nil {
53+
redisClient.Close()
54+
redisClient = nil
3555
return fmt.Errorf("could not connect to Redis: %v", err)
3656
}
3757

38-
// fmt.Print("Redis connected successfully\n")
58+
if os.Getenv("FIBER_PREFORK_CHILD") == "" {
59+
fmt.Print("Redis connected successfully\n")
60+
}
61+
3962
return nil
4063
}
4164

@@ -49,18 +72,29 @@ func (r *RedisClient) Set(key string, value interface{}, expirationSeconds int)
4972
}
5073

5174
func Get(key string) (string, error) {
52-
if redisClient == nil {
53-
if redisAddr != "" {
54-
err := InitRedis(redisAddr, redisPassword, redisDB)
55-
if err != nil {
56-
return "", fmt.Errorf("redis client not initialized and re-initialization failed: %v", err)
75+
clientMutex.RLock()
76+
client := redisClient
77+
clientMutex.RUnlock()
78+
79+
if client == nil {
80+
clientMutex.Lock()
81+
if redisClient == nil {
82+
if redisAddr != "" {
83+
err := InitRedis(redisAddr, redisPassword, redisDB)
84+
if err != nil {
85+
clientMutex.Unlock()
86+
return "", fmt.Errorf("redis client not initialized and re-initialization failed: %v", err)
87+
}
88+
} else {
89+
clientMutex.Unlock()
90+
return "", fmt.Errorf("redis client not initialized. Call InitRedis() first")
5791
}
58-
} else {
59-
return "", fmt.Errorf("redis client not initialized. Call InitRedis() first")
6092
}
93+
client = redisClient
94+
clientMutex.Unlock()
6195
}
6296

63-
val, err := redisClient.Get(ctx, key).Result()
97+
val, err := client.Get(ctx, key).Result()
6498
if err != nil {
6599
if err == redis.Nil {
66100
return "", nil
@@ -72,12 +106,24 @@ func Get(key string) (string, error) {
72106

73107
func NewRedisClient(addr string, password string, db int) *RedisClient {
74108
rdb := redis.NewClient(&redis.Options{
75-
Addr: addr,
76-
Password: password,
77-
DB: db,
109+
Addr: addr,
110+
Password: password,
111+
DB: db,
112+
PoolSize: 10,
113+
MinIdleConns: 5,
114+
MaxRetries: 3,
115+
PoolTimeout: time.Second * 4,
116+
IdleTimeout: time.Minute * 5,
117+
DialTimeout: time.Second * 5,
118+
ReadTimeout: time.Second * 3,
119+
WriteTimeout: time.Second * 3,
120+
PoolFIFO: false,
78121
})
79122

80-
_, err := rdb.Ping(ctx).Result()
123+
ctxTimeout, cancel := context.WithTimeout(ctx, time.Second*5)
124+
defer cancel()
125+
126+
_, err := rdb.Ping(ctxTimeout).Result()
81127
if err != nil {
82128
panic(fmt.Errorf("could not connect to Redis: %v", err))
83129
}
@@ -86,19 +132,30 @@ func NewRedisClient(addr string, password string, db int) *RedisClient {
86132
}
87133

88134
func Set(key string, value interface{}, expirationSeconds int) error {
89-
if redisClient == nil {
90-
if redisAddr != "" {
91-
err := InitRedis(redisAddr, redisPassword, redisDB)
92-
if err != nil {
93-
return fmt.Errorf("redis client not initialized and re-initialization failed: %v", err)
135+
clientMutex.RLock()
136+
client := redisClient
137+
clientMutex.RUnlock()
138+
139+
if client == nil {
140+
clientMutex.Lock()
141+
if redisClient == nil {
142+
if redisAddr != "" {
143+
err := InitRedis(redisAddr, redisPassword, redisDB)
144+
if err != nil {
145+
clientMutex.Unlock()
146+
return fmt.Errorf("redis client not initialized and re-initialization failed: %v", err)
147+
}
148+
} else {
149+
clientMutex.Unlock()
150+
return fmt.Errorf("redis client not initialized. Call InitRedis() first")
94151
}
95-
} else {
96-
return fmt.Errorf("redis client not initialized. Call InitRedis() first")
97152
}
153+
client = redisClient
154+
clientMutex.Unlock()
98155
}
99156

100157
expiration := time.Duration(expirationSeconds) * time.Second
101-
err := redisClient.Set(ctx, key, value, expiration).Err()
158+
err := client.Set(ctx, key, value, expiration).Err()
102159
if err != nil {
103160
return fmt.Errorf("could not set value in Redis: %v", err)
104161
}

0 commit comments

Comments
 (0)