Skip to content

Commit 45268ba

Browse files
committed
refactor: added mutexes to prevent multiple open connections or multiple disconnections
1 parent 5715f11 commit 45268ba

File tree

7 files changed

+137
-31
lines changed

7 files changed

+137
-31
lines changed

mongodb/connection.go

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
11
package mongodb
22

33
import (
4+
"sync"
5+
46
godatabases "github.com/ralvarezdev/go-databases"
57
"go.mongodb.org/mongo-driver/mongo"
68
"go.mongodb.org/mongo-driver/mongo/options"
79
"golang.org/x/net/context"
810
)
911

1012
type (
11-
// ConnHandler interface
12-
ConnHandler interface {
13-
Connect() (*mongo.Client, error)
14-
Client() (*mongo.Client, error)
15-
Disconnect()
16-
}
17-
1813
// DefaultConnHandler struct
1914
DefaultConnHandler struct {
2015
ctx context.Context
2116
cancel context.CancelFunc
2217
clientOptions *options.ClientOptions
2318
client *mongo.Client
19+
mutex sync.Mutex
2420
}
2521
)
2622

@@ -65,6 +61,10 @@ func (d *DefaultConnHandler) Connect() (*mongo.Client, error) {
6561
return nil, godatabases.ErrNilConnHandler
6662
}
6763

64+
// Lock the mutex to ensure thread safety
65+
d.mutex.Lock()
66+
defer d.mutex.Unlock()
67+
6868
// Check if the connection is already established
6969
if d.client != nil {
7070
return d.client, godatabases.ErrAlreadyConnected
@@ -101,6 +101,10 @@ func (d *DefaultConnHandler) Client() (*mongo.Client, error) {
101101
return nil, godatabases.ErrNilConnHandler
102102
}
103103

104+
// Lock the mutex to ensure thread safety
105+
d.mutex.Lock()
106+
defer d.mutex.Unlock()
107+
104108
// Check if the connection is established
105109
if d.client == nil {
106110
return nil, godatabases.ErrNotConnected
@@ -110,19 +114,31 @@ func (d *DefaultConnHandler) Client() (*mongo.Client, error) {
110114
}
111115

112116
// Disconnect closes the MongoDB client connection
113-
func (d *DefaultConnHandler) Disconnect() {
117+
//
118+
// Returns:
119+
//
120+
// - error: error if any
121+
func (d *DefaultConnHandler) Disconnect() error {
114122
if d == nil {
115-
return
123+
return nil
116124
}
117125

126+
// Lock the mutex to ensure thread safety
127+
d.mutex.Lock()
128+
defer d.mutex.Unlock()
129+
118130
// Check if the connection is established
119131
if d.client == nil {
120-
return
132+
return nil
121133
}
122134

123135
// Close the connection
124136
d.cancel()
125137
if err := d.client.Disconnect(d.ctx); err != nil {
126-
panic(godatabases.ErrFailedToDisconnect)
138+
return err
127139
}
140+
141+
// Set the client to nil
142+
d.client = nil
143+
return nil
128144
}

mongodb/interfaces.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package mongodb
2+
3+
import (
4+
"go.mongodb.org/mongo-driver/mongo"
5+
)
6+
7+
type (
8+
// ConnHandler interface
9+
ConnHandler interface {
10+
Connect() (*mongo.Client, error)
11+
Client() (*mongo.Client, error)
12+
Disconnect() error
13+
}
14+
)

redis/connection.go

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,19 @@
11
package redis
22

33
import (
4+
"sync"
5+
46
"github.com/go-redis/redis/v8"
57
godatabases "github.com/ralvarezdev/go-databases"
68
"golang.org/x/net/context"
79
)
810

911
type (
10-
// ConnHandler interface
11-
ConnHandler interface {
12-
Connect() (*redis.Client, error)
13-
Client() (*redis.Client, error)
14-
Disconnect()
15-
}
16-
1712
// DefaultConnHandler struct
1813
DefaultConnHandler struct {
1914
client *redis.Client
2015
clientOptions *redis.Options
16+
mutex sync.Mutex
2117
}
2218
)
2319

@@ -63,6 +59,10 @@ func (d *DefaultConnHandler) Connect() (*redis.Client, error) {
6359
return nil, godatabases.ErrNilConnHandler
6460
}
6561

62+
// Mutex lock to ensure thread safety
63+
d.mutex.Lock()
64+
defer d.mutex.Unlock()
65+
6666
// Check if the connection is already established
6767
if d.client != nil {
6868
return d.client, godatabases.ErrAlreadyConnected
@@ -94,6 +94,10 @@ func (d *DefaultConnHandler) Client() (*redis.Client, error) {
9494
return nil, godatabases.ErrNilConnHandler
9595
}
9696

97+
// Mutex lock to ensure thread safety
98+
d.mutex.Lock()
99+
defer d.mutex.Unlock()
100+
97101
// Check if the connection is established
98102
if d.client == nil {
99103
return nil, godatabases.ErrNotConnected
@@ -103,18 +107,30 @@ func (d *DefaultConnHandler) Client() (*redis.Client, error) {
103107
}
104108

105109
// Disconnect closes the Redis client connection
106-
func (d *DefaultConnHandler) Disconnect() {
110+
//
111+
// Returns:
112+
//
113+
// - error: error if the disconnection fails
114+
func (d *DefaultConnHandler) Disconnect() error {
107115
if d == nil {
108-
return
116+
return godatabases.ErrNilConnHandler
109117
}
110118

119+
// Mutex lock to ensure thread safety
120+
d.mutex.Lock()
121+
defer d.mutex.Unlock()
122+
111123
// Check if the connection is established
112124
if d.client == nil {
113-
return
125+
return nil
114126
}
115127

116128
// Close the connection
117129
if err := d.client.Close(); err != nil {
118-
panic(godatabases.ErrFailedToDisconnect)
130+
return godatabases.ErrFailedToDisconnect
119131
}
132+
133+
// Set the client to nil
134+
d.client = nil
135+
return nil
120136
}

redis/interfaces.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package redis
2+
3+
import (
4+
"github.com/go-redis/redis/v8"
5+
)
6+
7+
type (
8+
// ConnHandler interface
9+
ConnHandler interface {
10+
Connect() (*redis.Client, error)
11+
Client() (*redis.Client, error)
12+
Disconnect() error
13+
}
14+
)

sql/connection.go

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,17 @@ package sql
22

33
import (
44
"database/sql"
5+
"sync"
56

67
godatabases "github.com/ralvarezdev/go-databases"
78
)
89

910
type (
10-
// ConnHandler interface
11-
ConnHandler interface {
12-
Connect() (*sql.DB, error)
13-
DB() (*sql.DB, error)
14-
Disconnect()
15-
}
16-
1711
// DefaultConnHandler struct
1812
DefaultConnHandler struct {
1913
config Config
2014
db *sql.DB
15+
mutex sync.Mutex
2116
}
2217
)
2318

@@ -54,6 +49,10 @@ func (d *DefaultConnHandler) Connect() (*sql.DB, error) {
5449
return nil, godatabases.ErrNilConnHandler
5550
}
5651

52+
// Lock the mutex to ensure thread safety
53+
d.mutex.Lock()
54+
defer d.mutex.Unlock()
55+
5756
// Open a new connection
5857
db, err := sql.Open(d.config.DriverName(), d.config.DataSourceName())
5958
if err != nil {
@@ -89,6 +88,10 @@ func (d *DefaultConnHandler) DB() (*sql.DB, error) {
8988
return nil, godatabases.ErrNilConnHandler
9089
}
9190

91+
// Lock the mutex to ensure thread safety
92+
d.mutex.Lock()
93+
defer d.mutex.Unlock()
94+
9295
if d.db == nil {
9396
return nil, godatabases.ErrNotConnected
9497
}
@@ -97,15 +100,30 @@ func (d *DefaultConnHandler) DB() (*sql.DB, error) {
97100
}
98101

99102
// Disconnect closes the SQL connection
100-
func (d *DefaultService) Disconnect() error {
103+
//
104+
// Returns:
105+
//
106+
// - error: if any error occurred
107+
func (d *DefaultConnHandler) Disconnect() error {
101108
if d == nil {
102109
return godatabases.ErrNilConnHandler
103110
}
104111

112+
// Lock the mutex to ensure thread safety
113+
d.mutex.Lock()
114+
defer d.mutex.Unlock()
115+
105116
// Check if the connection is established
106117
if d.db == nil {
107118
return nil
108119
}
109120

110-
return d.db.Close()
121+
// Close the connection
122+
if err := d.db.Close(); err != nil {
123+
return err
124+
}
125+
126+
// Set the connection to nil
127+
d.db = nil
128+
return nil
111129
}

sql/interfaces.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ type (
1616
ConnectionMaxIdleTime() time.Duration
1717
}
1818

19+
// ConnHandler interface
20+
ConnHandler interface {
21+
Connect() (*sql.DB, error)
22+
DB() (*sql.DB, error)
23+
Disconnect()
24+
}
25+
1926
// Service is the interface for the service
2027
Service interface {
2128
DB() *sql.DB

sql/pgxpool/pool.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package pgxpool
22

33
import (
44
"context"
5+
"sync"
56

67
"github.com/jackc/pgx/v5/pgxpool"
78
godatabases "github.com/ralvarezdev/go-databases"
@@ -12,6 +13,7 @@ type (
1213
DefaultPoolHandler struct {
1314
config Config
1415
pool *pgxpool.Pool
16+
mutex sync.Mutex
1517
}
1618
)
1719

@@ -31,6 +33,14 @@ func NewDefaultPoolHandler(
3133

3234
// Connect returns a new connection pool
3335
func (d *DefaultPoolHandler) Connect() (*pgxpool.Pool, error) {
36+
if d == nil {
37+
return nil, godatabases.ErrNilConnHandler
38+
}
39+
40+
// Lock the mutex to ensure thread safety
41+
d.mutex.Lock()
42+
defer d.mutex.Unlock()
43+
3444
// Get the parsed configuration
3545
config, err := d.config.ParsedConfig()
3646
if err != nil {
@@ -60,6 +70,10 @@ func (d *DefaultPoolHandler) Pool() (*pgxpool.Pool, error) {
6070
return nil, godatabases.ErrNilPoolHandler
6171
}
6272

73+
// Lock the mutex to ensure thread safety
74+
d.mutex.Lock()
75+
defer d.mutex.Unlock()
76+
6377
// Check if the connection is established
6478
if d.pool == nil {
6579
return nil, godatabases.ErrNotConnected
@@ -74,11 +88,18 @@ func (d *DefaultPoolHandler) Disconnect() {
7488
return
7589
}
7690

91+
// Lock the mutex to ensure thread safety
92+
d.mutex.Lock()
93+
defer d.mutex.Unlock()
94+
7795
// Check if the connection is established
7896
if d.pool == nil {
7997
return
8098
}
8199

82100
// Close the connection pool
83101
d.pool.Close()
102+
103+
// Set the pool to nil
104+
d.pool = nil
84105
}

0 commit comments

Comments
 (0)