// Package txctx propagates a GORM transaction through a context.Context so that // repositories transparently join a caller's transaction. A service starts a // transaction, stashes the *gorm.DB tx with With, and calls its existing // repository methods unchanged; those repositories resolve the handle with DB. package txctx import ( "context" "gorm.io/gorm" ) type key struct{} // With returns a context carrying the given transaction handle. func With(ctx context.Context, tx *gorm.DB) context.Context { return context.WithValue(ctx, key{}, tx) } // DB returns the transaction bound to ctx when present, otherwise the fallback // db scoped to ctx. Repositories should use this instead of their raw db handle // so a single statement runs standalone while orchestrated writes join the // caller's transaction. func DB(ctx context.Context, fallback *gorm.DB) *gorm.DB { if tx, ok := ctx.Value(key{}).(*gorm.DB); ok && tx != nil { return tx } return fallback.WithContext(ctx) }