Reputation: 243
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?
Upvotes: 1
Views: 2073
Reputation: 1
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
Upvotes: 0
Reputation: 374
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()
}
Upvotes: 1