add `(*Engine) TransactionContext(...)`
This commit is contained in:
parent
914f2db9ea
commit
b081b9196d
27
engine.go
27
engine.go
|
@ -1416,6 +1416,11 @@ func (engine *Engine) SetDefaultContext(ctx context.Context) {
|
||||||
engine.defaultContext = ctx
|
engine.defaultContext = ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDefaultContext get the default context
|
||||||
|
func (engine *Engine) GetDefaultContext() context.Context {
|
||||||
|
return engine.defaultContext
|
||||||
|
}
|
||||||
|
|
||||||
// PingContext tests if database is alive
|
// PingContext tests if database is alive
|
||||||
func (engine *Engine) PingContext(ctx context.Context) error {
|
func (engine *Engine) PingContext(ctx context.Context) error {
|
||||||
session := engine.NewSession()
|
session := engine.NewSession()
|
||||||
|
@ -1443,3 +1448,25 @@ func (engine *Engine) Transaction(f func(*Session) (interface{}, error)) (interf
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// !datbeohbbh! Transaction Execute sql wrapped in a transaction with provided context
|
||||||
|
func (engine *Engine) TransactionContext(ctx context.Context, f func(context.Context, *Session) (interface{}, error)) (interface{}, error) {
|
||||||
|
session := engine.NewSession().Context(ctx)
|
||||||
|
defer session.Close()
|
||||||
|
|
||||||
|
if err := session.Begin(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer session.Rollback()
|
||||||
|
|
||||||
|
result, err := f(ctx, session)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := session.Commit(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
|
@ -84,6 +84,48 @@ func TestAutoTransaction(t *testing.T) {
|
||||||
assert.EqualValues(t, false, has)
|
assert.EqualValues(t, false, has)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTransactionContext(t *testing.T) {
|
||||||
|
assert.NoError(t, PrepareEngine())
|
||||||
|
|
||||||
|
type TestTxContext struct {
|
||||||
|
Id int64 `xorm:"autoincr pk"`
|
||||||
|
Msg string `xorm:"varchar(255)"`
|
||||||
|
Created time.Time `xorm:"created"`
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NoError(t, testEngine.Sync(&TestTxContext{}))
|
||||||
|
|
||||||
|
engine := testEngine.(*xorm.Engine)
|
||||||
|
ctx, cancel := context.WithTimeout(engine.GetDefaultContext(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
// will success
|
||||||
|
_, err := engine.TransactionContext(ctx, func(ctx context.Context, session *xorm.Session) (interface{}, error) {
|
||||||
|
_, err := session.Insert(TestTxContext{Msg: "hi"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
has, err := engine.Exist(&TestTxContext{Msg: "hi"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, has)
|
||||||
|
|
||||||
|
// will rollback
|
||||||
|
_, err = engine.TransactionContext(ctx, func(ctx context.Context, session *xorm.Session) (interface{}, error) {
|
||||||
|
_, err := session.Insert(TestTxContext{Msg: "hello"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("rollback")
|
||||||
|
})
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
has, err = engine.Exist(&TestTxContext{Msg: "hello"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.False(t, has)
|
||||||
|
}
|
||||||
|
|
||||||
func assertSync(t *testing.T, beans ...interface{}) {
|
func assertSync(t *testing.T, beans ...interface{}) {
|
||||||
for _, bean := range beans {
|
for _, bean := range beans {
|
||||||
t.Run(testEngine.TableName(bean, true), func(t *testing.T) {
|
t.Run(testEngine.TableName(bean, true), func(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue