Home > Back-end >  Keep mongoDB client connected Golang
Keep mongoDB client connected Golang

Time:10-28

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 ?

CodePudding user response:

About the issue concerning the disconnection of the client, that was my bad.

I was returning err in ConnectToDatabase() 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 :)

CodePudding user response:

The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.

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 line s.Shutdown(ctxTimeOut).

  • Related