J'utilise le pilote Golanggo.mongodb.org/mongo-driver/mongo
pour apprendre les transactions MongoDB. Je suis ceci donc répondez et cet exemple sur github.
Exemple de code donné par @simagix :
if session, err = client.StartSession(); err != nil { t.Fatal(err) } if err = session.StartTransaction(); err != nil { t.Fatal(err) } if err = mongo.WithSession(ctx, session, func(sc mongo.SessionContext) error { if result, err = collection.UpdateOne(sc, bson.M{"_id": id}, update); err != nil { t.Fatal(err) } if result.MatchedCount != 1 || result.ModifiedCount != 1 { t.Fatal("replace failed, expected 1 but got", result.MatchedCount) } // more interrelated operations ... if err = session.CommitTransaction(sc); err != nil { t.Fatal(err) } return nil }); err != nil { t.Fatal(err) } session.EndSession(ctx)
Dans les deux exemples, ils ne seront pas annulés si une erreur se produit. Je sais que c'est un exemple de démonstration. Mais quand je fais la même chose dans le code, ça marche bien.
Est-il possible d'omettre la restauration lorsqu'une erreur se produit (le pilote la gère-t-il) ? Ou est-ce que j'ai raté quelque chose ?
mongo.withsession()
ne suppose aucune transaction active, elle permet "seulement" d'exécuter des rappels dans le cadre d'une session donnée. Par conséquent, si vous souhaitez qu'il soit exécuté dans le cadre de la transaction initiée, vous devez gérer la validation et l'abandonner vous-même. Cela permet un contrôle plus fin.
Cependant, si vous envisagez d'exécuter le rappel en tant que transaction, utilisez session.withtransaction()
car il gère les transactions et leur cycle de vie de manière transparente : il crée la transaction et la valide ou l'abandonne en fonction de l'erreur renvoyée par le rappel. En tant que fonctionnalité supplémentaire, il peut également gérer les tentatives. Comme le souligne également sa documentation :
Si le rappel échoue, le conducteur appellera aborttransaction.
Voici un exemple simple de la façon d'exécuter correctement les rappels au sein d'une transaction :
var docToInsert, idToUpdate, updateDoc any func doInTransactionExample(ctx context.Context, client *mongo.Client) error { sess, err := client.StartSession(options.Session().SetDefaultReadConcern(readconcern.Majority())) if err != nil { return fmt.Errorf("client.StartSession() error: %w", err) } defer sess.EndSession(ctx) result, err := sess.WithTransaction( ctx, func(sessCtx mongo.SessionContext) (any, error) { // sessCtx must be used as context.Context for all operations to be run in the transaction. var ctx context.Context = sessCtx // Shadow ctx on purpose! c := client.Database("foo").Collection("bar") // Insert example if _, err := c.InsertOne(ctx, docToInsert); err != nil { return nil, fmt.Errorf("InsertOne() failed: %w", err) } // Update example if ur, err := c.UpdateByID(ctx, idToUpdate, updateDoc); err != nil { return nil, fmt.Errorf("UpdateByID() failed: %w", err) } else { if ur.MatchedCount == 0 { return nil, fmt.Errorf("UpdateByID() failed: %w", mongo.ErrNoDocuments) } } return "arbitrary-result-to-return", nil }, options.Transaction().SetReadPreference(readpref.PrimaryPreferred()), ) if err != nil { return fmt.Errorf("sess.WithTransaction() error: %w", err) } _ = result // Not using result return nil }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!