[GODRIVER-704] Document that mongo.SessionContext is not goroutine safe Created: 14/Dec/18  Updated: 28/Oct/23  Resolved: 30/Jan/19

Status: Closed
Project: Go Driver
Component/s: Documentation
Affects Version/s: 0.1.0
Fix Version/s: 0.3.0

Type: Improvement Priority: Minor - P4
Reporter: xwp50419 Assignee: Isabella Siu (Inactive)
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

mongo:latest


Issue Links:
Related
is related to GODRIVER-716 SessionContext not being goroutine sa... Closed

 Description   

Since mongo.SessionContext is not goroutine safe and it should be documented as such.

func MongoContext(txn bool) (mongo.SessionContext, error) {
	var mctx mongo.SessionContext
	if !txn {
		return mctx, nil
	}
 
	sess, err := client.StartSession()
	if err != nil {
		return nil, err
	}
 
	err = sess.StartTransaction()
	if err != nil {
		return nil, err
	}
 
	_ = mongo.WithSession(context.Background(), sess, func(sessionContext mongo.SessionContext) error {
		mctx = sessionContext
		return nil
	})
 
	return mctx, nil
}
 
func ErrorExample(ctx context.Context, in *pb.Mock) (res MockResponse, err error) {
	mctx, err := MongoContext(true)
	if err != nil {
		return
	}
 
	params, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return
	}
 
	var wg sync.WaitGroup
	var err1, err2, err3 error
 
	wg.Add(1)
	go func() {
		defer wg.Done()
		_, err1 = collection1.SomeOperation(mctx, params)
	}()
 
	wg.Add(1)
	go func() {
		defer wg.Done()
		_, err2 = collection2.SomeOperation(mctx, params)
	}()
 
	wg.Add(1)
	go func() {
		defer wg.Done()
		_, err3 = collection3.SomeOperation(mctx, params)
	}()
 
	wg.Wait()
 
	if err1 != nil {
		return res, err1
	}
	if err2 != nil {
		return res, err2
	}
	if err3 != nil {
		return res, err3
	}
 
	err = mctx.CommitTransaction(context.Background())
	if err != nil {
		return
	}
 
	return &MockResponse{
		Success: true,
	}, nil
}
 
func WorkaroundExmaple(ctx context.Context, in *pb.Mock) (res MockResponse, err error) {
	mctx, err := MongoContext(true)
	if err != nil {
		return
	}
 
	params, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return
	}
 
	_, err = collection1.SomeOperation(mctx, params)
	if err != nil {
		return
	}
 
	var wg sync.WaitGroup
	var err1, err2 error
 
	wg.Add(1)
	go func() {
		defer wg.Done()
		_, err1 = collection2.SomeOperation(mctx, params)
	}()
 
	wg.Add(1)
	go func() {
		defer wg.Done()
		_, err2 = collection3.SomeOperation(mctx, params)
	}()
 
	wg.Wait()
 
	if err1 != nil {
		return res, err1
	}
	if err2 != nil {
		return res, err2
	}
 
	err = mctx.CommitTransaction(context.Background())
	if err != nil {
		return
	}
 
	return &MockResponse{
		Success: true,
	}, nil
}

The ErrorExample will randomly generate the following errors, even if I specified the TransactionOptions<options.Transaction().SetWriteConcern(writeconcern.New(writeconcern.WMajority())).SetReadConcern(readconcern.Majority()).SetReadPreference(readpref.Primary())> in sess.StartTransaction()
Only the first command in a transaction may specify a readConcern
Given transaction number 1 does not match any in-progress transactions.



 Comments   
Comment by Githook User [ 30/Jan/19 ]

Author:

{'username': 'iwysiu', 'email': 'isabella.siu@10gen.com', 'name': 'Isabella Siu'}

Message: GODRIVER-704 document that mongo.SessionContext is not goroutine safe

Change-Id: I167bda20f16716287331e29faff8fe9a11b3a84c
Branch: master
https://github.com/mongodb/mongo-go-driver/commit/2161eed7bba9cad730eef095310c296ec9a6cf89

Comment by Ian Whalen (Inactive) [ 07/Jan/19 ]

Need to document that you shouldn't be using SessionContext in multiple goroutines.

Comment by Kristofer Brandow (Inactive) [ 19/Dec/18 ]

Hi xwp50419,

By goroutine safe I mean that the SessionContext is not safe for concurrent use without coordination, because a Session is not safe for concurrent use. Using the SessionContext in multiple goroutines concurrently without coordination is not supported.

--Kris

Comment by xwp50419 [ 19/Dec/18 ]

Hi Kris,
I have done several tests on the SessionContext and I would say that it is safe to use the SessionContext with the goroutine as long as it has been initialised (completed the first command and change the finite state machine, just like the workaround example). It is more flexible to expose the SessionContext to the outer scope and use it as a regular context.Context.
– xwp50419

Comment by Kristofer Brandow (Inactive) [ 17/Dec/18 ]

Hi xwp50419,

The SessionContext type is not goroutine safe, so it cannot be used concurrently. You cannot pass the SessionContext to goroutines and it shouldn't escape the scope of the function passed to mongo.WithSession.

--Kris

Generated at Thu Feb 08 08:34:47 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.