Your Question
How should WithContext be combined with Transaction? I'm particularly thinking about reacting to a cancelation.
3 options I can see:
- Use it for both. My guess is this does nothing over (2)
func Do(ctx context.Context, db *gorm.DB) error {
return db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
for i := 0; i < 5; i++ {
if err := tx.WithContext(ctx).Query(...).Error; err != nil {
return err
}
}
}
}
- Use it at the top-level before initiating the transaction, but not within the
tx. I'm guessing the context trickles down so this would be the way to do it?
func Do(ctx context.Context, db *gorm.DB) error {
return db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
for i := 0; i < 5; i++ {
if err := tx.Query(...).Error; err != nil {
return err
}
}
}
}
- Skip it at the top-level and use it in each transaction sub-query. If my above guess is correct, then I think this accomplishes the same thing as (2), while requiring more effort at runtime.
func Do(ctx context.Context, db *gorm.DB) error {
return db.Transaction(func(tx *gorm.DB) error {
for i := 0; i < 5; i++ {
if err := tx.WithContext(ctx).Query(...).Error; err != nil {
return err
}
}
}
}
The document you expected this should be explained
Transactions and maybe Context
Expected answer
A recommendation as to which style is the most appropriate with dealing with contexts, particularly for responding to cancelations. If there's a reason to use one over the other, pro/con would be handy.
Comment From: black-06
Yes, No.2 is ok.
db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
// ...
})
Context is stored in Statement, so db and tx hold the same ctx
Comment From: jessdwitch
That's what I thought, but I appreciate the confirmation. Thank you!