I try to understand why my mongoDB client disconnect despite the global scope variable. There is something that i dont understand. I think, somehow, this is related the ConnectToDatabase()
function.
If i try to do some operation on the DB in the ConnectToDatabase()
function, it goes well but with another package, it keep return Client disconnected
error.
Here the structure of the project:
├── database
│ ├── connect.go
│ └── models
├── go.mod
├── go.sum
├── handlers
│ └── user.go
├── main.go
├── README.md
└── services
├── create-user.go
└── get-users.go
Here the code:
func main() {
fmt.Println("Users Data service started")
err := DB.ConnectToDatabase()
if err != nil {
log.Fatal(err)
}
l := log.New(os.Stdout, "service-user-data - ", log.LstdFlags)
userH := handlers.User(l)
sMux := http.NewServeMux()
sMux.Handle("/", userH)
s := &http.Server{
Addr: ":9090",
Handler: sMux,
IdleTimeout: 120 * time.Second,
ReadTimeout: 1 * time.Second,
WriteTimeout: 1 * time.Second,
}
go func() {
err := s.ListenAndServe()
if err != nil {
l.Fatal(err)
}
}()
sigChan := make(chan os.Signal)
signal.Notify(sigChan, os.Interrupt)
signal.Notify(sigChan, os.Kill)
// Wait for an available signal
// Then print the message into the channel
sig := <-sigChan
l.Println("Recieved terminated, gracefully shutdown", sig)
ctxTimeOut, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
s.Shutdown(ctxTimeOut)
}
const (
dbURI = "mongodb://localhost:27017"
)
// CtxDB represent the context fot the database
var CtxDB, cancel = context.WithTimeout(context.Background(), 10*time.Second)
// DBClient spread all over the application the mongoDB client
var DBClient, err = mongo.NewClient(options.Client().ApplyURI(dbURI))
// DB represent the service database
var DB = DBClient.Database("service-users-data")
// UserCollection represent the user collection
var UserCollection = DB.Collection("users")
// ConnectToDatabase function handle the connection to the connection o the database
// It will return either client and err
func ConnectToDatabase() (err error) {
err = DBClient.Connect(CtxDB)
if err != nil {
log.Fatal(err)
} else {
fmt.Println("Database's client connected")
}
err = DBClient.Ping(CtxDB, readpref.Primary())
if err != nil {
log.Fatal(err)
} else {
fmt.Println("Client pinged")
}
defer DBClient.Disconnect(CtxDB)
return err
}
type users = models.Users
// GetUsers function return a list of user
func GetUsers(resWriter http.ResponseWriter, req *http.Request) (u users) {
ctx := database.CtxDB
cursor, err := database.UserCollection.Find(ctx, bson.M{})
if err != nil {
log.Fatal(err)
}
if err = cursor.All(ctx, &u); err != nil {
log.Fatal(err)
}
return u
}
- Is this folder structure actually correct ?
- Why this client keep disconnecting ?
2
Answers
About the issue concerning the disconnection of the client, that was my bad.
I was returning
err
inConnectToDatabase()
function and my guess is that was stopping the execution of the function instead of letting the client do his job.But if anybody have the time to check a bit the code and the structure to give me a feedback about the practices, that could be great and well appreciated :)
When you set a
defer
clause, this will execute after the function it was defined in ends.Basically, your deferred database close is happening right after the
ConnectToDatabase
function is executed.My recommendation is that you return the
sql.DB
object and you disconnect only when the application itself terminates, maybe after the lines.Shutdown(ctxTimeOut)
.