0
\$\begingroup\$

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() 
}
asked Oct 26, 2021 at 5:09
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

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.

answered Nov 6, 2021 at 15:07
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.