Uploaded image for project: 'Go Driver'
  1. Go Driver
  2. GODRIVER-704

Document that mongo.SessionContext is not goroutine safe

    • Type: Icon: Improvement Improvement
    • Resolution: Fixed
    • Priority: Icon: Minor - P4 Minor - P4
    • 0.3.0
    • Affects Version/s: 0.1.0
    • Component/s: Documentation
    • None
    • Environment:
      mongo:latest

      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.

            Assignee:
            isabella.siu@mongodb.com Isabella Siu (Inactive)
            Reporter:
            xwp50419 xwp50419
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: