Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mongo manual session failed #4263

Open
Mikaelemmmm opened this issue Jul 20, 2024 · 0 comments
Open

mongo manual session failed #4263

Mikaelemmmm opened this issue Jul 20, 2024 · 0 comments
Labels
area/orm Categorizes issue or PR as related to orm.

Comments

@Mikaelemmmm
Copy link
Member

When mongo manually opens a transaction, the second parameter of mongo.NewSessionContext needs to pass its own session inside the mongo sdk, but this session cannot be obtained within the framework. I currently obtain it through reflection. The following is my temporary solution.

When performing specific db insert, update and other operations, it will be judged whether the session injected into ctx when mongo.NewSessionContext is its own session within the SDK. If not, it will not be treated as an open transaction.

mongo sdk logic:

https://github.com/mongodb/mongo-go-driver/blob/v1/mongo/collection.go#L268

https://github.com/mongodb/mongo-go-driver/blob/v1/mongo/session.go#L383

var ErrMongoSessionEmpty = errors.New("Start Transaction Mongo Session Empty")

func StartTransaction(ctx context.Context, client *mon.Model, txnFunc func(sc mongo.SessionContext) error) error {

	session, err := client.StartSession()
	if err != nil {
		return err
	}
	defer session.EndSession(ctx)

	err = session.StartTransaction()
	if err != nil {
		return err
	}

	// -------- need mongo sdk client session --------
	mongoSession := getMongoSession(session)
	if mongoSession == nil {
		return ErrMongoSessionEmpty
	}
	sessCtx := mongo.NewSessionContext(ctx, mongoSession)
	//  -------- need mongo sdk client session  -------- 
	
	
	defer func() {
		if err != nil {
			if abortErr := session.AbortTransaction(sessCtx); abortErr != nil {
				logx.WithContext(ctx).Errorf("session rollback failed , err:%v,abortErr:%v", err, abortErr)
			}
		}
	}()

	err = txnFunc(sessCtx)
	if err != nil {
		return err
	}

	err = session.CommitTransaction(sessCtx)
	if err != nil {
		return err
	}

	return nil
}

//  get mongo sdk session from reflection
func getMongoSession(sess mongo.Session) mongo.Session {
	sessValue := reflect.ValueOf(sess)
	if sessValue.Kind() == reflect.Ptr {
		sessValue = sessValue.Elem()
	}
	field := sessValue.FieldByName("Session")
	if field.IsValid() && field.CanInterface() {
		if innerSess, ok := field.Interface().(mongo.Session); ok {
			return innerSess
		}
	}
	return nil
}
@kevwan kevwan added the area/orm Categorizes issue or PR as related to orm. label Jul 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/orm Categorizes issue or PR as related to orm.
Projects
None yet
Development

No branches or pull requests

2 participants