Connection(localhost:27017[-4]) failed to write: context canceled

Viewed 2247

Here I read it's necessary to cancel the context. This is how my db.go looks like:

package db

import (
    "context"
    "fmt"
    "log"
    "os"
    "time"

    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

const (
    connectionStringTemplate = "mongodb://%s:%s@%s"
)

var DB *mongo.Client
var Ctx context.Context

// Connect with create the connection to MongoDB
func Connect() {
    username := os.Getenv("MONGODB_USERNAME")
    password := os.Getenv("MONGODB_PASSWORD")
    clusterEndpoint := os.Getenv("MONGODB_ENDPOINT")

    connectionURI := fmt.Sprintf(connectionStringTemplate, username, password, clusterEndpoint)

    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    client, err := mongo.NewClient(options.Client().ApplyURI(connectionURI))
    if err != nil {
        log.Printf("Failed to create client: %v", err)
    }

    err = client.Connect(ctx)
    if err != nil {
        log.Printf("Failed to connect to cluster: %v", err)
    }

    // Force a connection to verify our connection string
    err = client.Ping(ctx, nil)
    if err != nil {
        log.Printf("Failed to ping cluster: %v", err)
    }

    DB = client
    Ctx = ctx
    log.Printf("Connected to MongoDB!")
}

I execute this in the main.go:

func main() {

    // Configure
    db.Connect()
    defer db.DB.Disconnect(context.Background())

    r := gin.Default()

    // Routes
    //r.GET("/movies", handlers.GetAllMoviesHandler)
    r.POST("/movies", handlers.AddMovieHandler)

    // listen and serve on 0.0.0.0:8080
    r.Run()
}

and it works fine if my local mongodb is running. Now when I use the client like this (I know the naming is still bad):

func AddMovie(movie *Movie) (primitive.ObjectID, error) {
    movie.ID = primitive.NewObjectID()
    result, err := db.DB.Database("movies").Collection("movies").InsertOne(db.Ctx, movie)
    if err != nil {
        log.Printf("Could not create movie: %v", err)
        return primitive.NilObjectID, err
    }
    oid := result.InsertedID.(primitive.ObjectID)
    return oid, nil
}

I get an error like this

{"msg":{"Code":0,"Message":"connection(localhost:27017[-4]) failed to write: context canceled","Labels":["NetworkError","RetryableWriteError"],"Name":"","Wrapped":{"ConnectionID":"localhost:27017[-4]","Wrapped":{}}}}

It works fine when I put the defer cancel() in comment but I suppose this is not correct?. What am I doing wrong here.

Update:

It works when I use: result, err :=db.DB.Database("movies").Collection("movies").InsertOne(context.Background(), movie) instead of ctx. I don't fully understand the usage of the context in these use case. I'm not sure if I should do the Ctx = ctx in the Connect function either.

0 Answers
Related