1

I'm making multiple goroutines share a single connection by passing client as an argument.

uri := "mongodb://localhost:27017"
ctx := context.Background()
client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))

go Foo(client)
go Bar(client)

func Foo(client *mongo.Client) {
        // ... 
}

func Bar(client *mongoClient) {
        // ...
}

I'm confused about what to do with ctx. Should I create a new context everytime I query to the database, or should I reuse context just like the client?

2 Answers 2

1

It depends on how your Foo and Bar methods behave. Let's imagine the Foo method is a simple short-lived goroutine that makes one query to DB and the only thing you want is to check if its parent context is not Done or Cancelled. Then you can provide parent context to your Foo method.

func main() {
    uri := "mongodb://localhost:27017"
    ctx := context.Background()
    client, err := Connect(ctx, uri)

    ctx, cancel := context.WithCancel(ctx)

    
    if err != nil {
        panic(err)
    }

    go Foo(ctx, client)
    go Bar(context.WithValue(ctx, "uri", uri), client)

    // cancel parent context
    cancel()

    time.Sleep(5*time.Second)
}

func Foo(ctx context.Context, client *Client) {
    fmt.Printf("Foo: %s\n", ctx.Value("uri"))
    select {
        case <- ctx.Done():
            err := ctx.Err()
            if err != nil {
                // you could switch for the actual reason
                fmt.Println("In our case context canceled: ", err)
                return
            }
            fmt.Printf("Do something...")
    }
}

On the other hand, if Bar performs some non-trivial logic and makes more than one call to DB you probably want a separate context to be able to cancel it separately from your parent context. Then you could derive a new context from your parent.

func Bar(ctx context.Context, client *Client) {
    // Bar has a non trivial logic and needs a separate cancellation and handling
    ctx, cancelFunc := context.WithCancel(ctx)
    fmt.Printf("Bar: %s\n", ctx.Value("uri"))
    
    // cancel derived context
    cancelFunc()

}
Sign up to request clarification or add additional context in comments.

Comments

0

I have also done it like this

type DB struct {
    client *mongo.Client
}

func (db *DB) GetVideoStream {}

func main() {
    ctx, _ := context.WithTimeout(context.Background(), 60*time.Second)
    client, err := mongo.Connect(ctx, clientOpts)
    db := &DB{client: client}
    go db.GetVideoStream()
    http.HandleFunc("/api/", db.GetVideoStream)
}

You can use pointer receivers to do the same thing.

I am new still new to the language

Comments

Your Answer

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.