\$\begingroup\$
\$\endgroup\$
Created a MongoDB client which is handling the retry in case of server connection failure. Please review and how I can improve further.
package db
import (
"context"
"errors"
"log"
"time"
"go.mongodb.org/mongo-driver/event"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
const SupplyReportDB = "abc"
const SupplyAlertsCollection = "abc"
type MongoDB struct {
client *mongo.Client
uri string
}
func NewMongoDBCon(context context.Context, uri string) (*MongoDB, error) {
var conn = &MongoDB{uri: uri}
client, err := conn.Connect(context)
if err != nil {
return conn, err
}
conn.client = client
return conn, err
}
func (m *MongoDB) Connect(context context.Context) (*mongo.Client, error) {
serverMonitor := &event.ServerMonitor{
ServerHeartbeatFailed: m.serverHandler,
}
client, err := mongo.Connect(
context, options.Client().
ApplyURI(m.uri).
SetHeartbeatInterval(5*time.Second).
SetServerMonitor(serverMonitor),
)
if err != nil {
return client, err
}
if err := client.Ping(context, nil); err != nil {
return client, errors.New("not connected")
}
return client, nil
}
func (m *MongoDB) Close(context context.Context) error {
if err := m.client.Disconnect(context); err != nil {
return err
}
return nil
}
func (m *MongoDB) GetSupplyAlertCollection() *mongo.Collection {
collection := m.client.Database(SupplyReportDB).Collection(SupplyAlertsCollection)
return collection
}
func (m *MongoDB) reconnect() {
count := 1
for {
if count == 3{
log.Fatal("Problem in connecting MongoDB.. exiting..")
}
log.Println("Retrying for the ", count, "time")
client, err := m.Connect(context.TODO())
if err != nil {
time.Sleep(4 * time.Second)
} else {
log.Println("Reconnected successfully.")
m.client = client
break
}
count++
}
}
func (m *MongoDB)serverHandler(evt *event.ServerHeartbeatFailedEvent) {
m.reconnect()
}
1 Answer 1
\$\begingroup\$
\$\endgroup\$
I would think about replacing the "for loop" with a retry package https://github.com/avast/retry-go. Should be a little bit cleaner.
func (m *MongoDB) reconnect() {
err := retry.Do(func() error {
client, err := mongo.Connect(context.TODO(), m.uri, mongo.ConnectTimeout(5*time.Second))
if err != nil {
log.Printf("Failed to connect to MongoDB at %s: %s", m.uri, err)
return err
}
log.Println("Reconnected successfully.")
m.client = client
return nil
},
retry.Attempts(3),
retry.Delay(4*time.Second),
retry.OnRetry(func(n uint, err error) {
log.Printf("Retry %d: %s", n, err)
}),
)
if err != nil {
log.Fatal("Problem in connecting MongoDB.. exiting..")
}}
Also using exponential backoff (in the delay) could be an option.
lang-golang