Skip to content

Transactions

// Use engine to execute transaction
err := engine.WithTransaction(ctx, func(txCtx context.Context) error {
// Execute operations in transaction
session := pie.Table[User](engine)
// Insert user
_, err := session.Insert(txCtx, &User{Name: "Transaction User"})
if err != nil {
return err
}
// Update other collection
orderSession := pie.Table[Order](engine)
_, err = orderSession.Insert(txCtx, &Order{UserID: userID})
return err
})
// Use transaction manager
tx := pie.MustTransaction(engine)
err = tx.Transaction(ctx, func(txCtx context.Context) error {
// Transaction operations
return nil
})
func TransferPoints(fromUserID, toUserID bson.ObjectID, points int) error {
return engine.WithTransaction(ctx, func(txCtx context.Context) error {
session := pie.Table[User](engine)
// Check sender user
fromUser, err := session.Where("_id", fromUserID).FindOne(txCtx)
if err != nil {
return err
}
// Check if user has enough points
if fromUser.Points < points {
return errors.New("insufficient points")
}
// Check receiver user
_, err = session.Where("_id", toUserID).FindOne(txCtx)
if err != nil {
return err
}
// Deduct points from sender
_, err = session.Where("_id", fromUserID).Update(txCtx,
bson.D{{"$inc", bson.D{{"points", -points}}}})
if err != nil {
return err
}
// Add points to receiver
_, err = session.Where("_id", toUserID).Update(txCtx,
bson.D{{"$inc", bson.D{{"points", points}}}})
if err != nil {
return err
}
return nil
})
}
func UseTransactionManager() error {
tx := pie.MustTransaction(engine)
return tx.Transaction(ctx, func(txCtx context.Context) error {
session := pie.Table[User](engine)
// Insert user
user := &User{Name: "John Doe", Email: "john@example.com"}
result, err := session.Insert(txCtx, user)
if err != nil {
return err
}
// Insert user profile
profile := &Profile{UserID: result.InsertedID, Bio: "Software Developer"}
_, err = pie.Table[Profile](engine).Insert(txCtx, profile)
if err != nil {
return err
}
return nil
})
}
func TransactionWithErrorHandling() error {
return engine.WithTransaction(ctx, func(txCtx context.Context) error {
session := pie.Table[User](engine)
// Try to insert user
user := &User{Name: "John Doe", Email: "john@example.com"}
_, err := session.Insert(txCtx, user)
if err != nil {
// Transaction will be rolled back automatically
return fmt.Errorf("failed to insert user: %w", err)
}
// Try to insert profile
profile := &Profile{UserID: user.ID, Bio: "Software Developer"}
_, err = pie.Table[Profile](engine).Insert(txCtx, profile)
if err != nil {
// Transaction will be rolled back automatically
return fmt.Errorf("failed to insert profile: %w", err)
}
return nil
})
}