Actual:
Standalone servers support sessions, but the driver errors if a retryable write is done in an explicit session because we add a txnNumber field. We should only add the txnNumber for replica sets and sharded clusters.
Original:
Coming from the mgo community driver, I have discovered sessions in the mongo-go-driver rely on 'server sessions'. As an application developer, I am forced to now know what mongo topology the end user is running, with no apparent way to do so, in order to detect if server sessions can be used or not.
It would be preferable if sessions become a no-op if a single mongo is used instead of getting what will appear to most users as an unrelated error due to the advent of multi-document transactions:
"Transaction numbers are only allowed on a replica set member or mongos"
I only discovered this was an issue in a library I have created after migrating to mongo-driver once I had control over the session/context via v1.4.0. This is also somewhat related to mongo version/feature detection for enabling transactions: GODRIVER-1732
This localhost repro shows the failure when running on a single mongo:
package main import ( "context" log "github.com/sirupsen/logrus" "go.mongodb.org/mongo-driver/mongo" ) type Bar struct { Name string Type string Rating int } func main() { ctx := context.Background() client, err := mongo.Connect(ctx) if err != nil { log.WithError(err).Fatal("Unable to build mongo connection!") } sess, _ := client.StartSession() err = mongo.WithSession(ctx, sess, func(ctx mongo.SessionContext) error { // check connection works as mongo-go lazily connects. err = client.Ping(ctx, nil) if err != nil { log.WithError(err).Error("Unable to connect to mongo! Have you configured your connection properly?") return err } bar := Bar{ Name: "Moro Bar", Type: "Chocolate", Rating: 10, } res, err := client.Database("foo").Collection("bar").InsertOne(ctx, bar) if err != nil { log.WithError(err).Fatal("unable to insert a foobar") return err } log.WithField("id", res.InsertedID).Info("inserted bar") return nil }) if err != nil { log.WithError(err).Fatal("unable to insert a fooMorobar") } }
The mongo-driver paradigm will throw people off migrating from mgo. At the minimum it should be documented that mongo sessions require a replica set.