txwrap can now be properly nested. add json conversion functions to quick

This commit is contained in:
sawka
2022-07-12 16:10:46 -07:00
parent 6351082900
commit 11087c10be
4 changed files with 71 additions and 33 deletions
+11 -3
View File
@@ -10,7 +10,7 @@ import (
)
func NumSessions(ctx context.Context) (int, error) {
db, err := GetDB()
db, err := GetDB(ctx)
if err != nil {
return 0, err
}
@@ -71,7 +71,7 @@ func InsertRemote(ctx context.Context, remote *RemoteType) error {
if remote == nil {
return fmt.Errorf("cannot insert nil remote")
}
db, err := GetDB()
db, err := GetDB(ctx)
if err != nil {
return err
}
@@ -156,7 +156,7 @@ func GetSessionById(ctx context.Context, id string) (*SessionType, error) {
}
func GetSessionByName(ctx context.Context, name string) (*SessionType, error) {
db, err := GetDB()
db, err := GetDB(ctx)
if err != nil {
return nil, err
}
@@ -228,6 +228,14 @@ func containsStr(strs []string, testStr string) bool {
return false
}
func InsertScreen(ctx context.Context, sessionId string, screenName string) (string, error) {
var newScreenId string
txErr := WithTx(ctx, func(tx *TxWrap) error {
return nil
})
return newScreenId, txErr
}
// if windowName == "", it will be generated
// returns (windowid, err)
func InsertWindow(ctx context.Context, sessionId string, windowName string) (string, error) {
+13 -5
View File
@@ -72,19 +72,27 @@ func quickJson(v interface{}) string {
}
func quickScanJson(ptr interface{}, val interface{}) error {
strVal, ok := val.(string)
barrVal, ok := val.([]byte)
if !ok {
return fmt.Errorf("cannot scan '%T' into '%T'", val, ptr)
strVal, ok := val.(string)
if !ok {
return fmt.Errorf("cannot scan '%T' into '%T'", val, ptr)
}
barrVal = []byte(strVal)
}
if strVal == "" {
if len(barrVal) == 0 {
return nil
}
return json.Unmarshal([]byte(strVal), ptr)
return json.Unmarshal(barrVal, ptr)
}
func quickValueJson(v interface{}) (driver.Value, error) {
if v == nil {
return "", nil
}
return json.Marshal(v)
barr, err := json.Marshal(v)
if err != nil {
return nil, err
}
return string(barr), nil
}
+8 -5
View File
@@ -43,7 +43,10 @@ func GetSessionDBName() string {
return path.Join(scHome, DBFileName)
}
func GetDB() (*sqlx.DB, error) {
func GetDB(ctx context.Context) (*sqlx.DB, error) {
if IsTxWrapContext(ctx) {
return nil, fmt.Errorf("cannot call GetDB from within a running transaction")
}
globalDBLock.Lock()
defer globalDBLock.Unlock()
if globalDB == nil && globalDBErr == nil {
@@ -69,7 +72,7 @@ func (opts *WindowOptsType) Scan(val interface{}) error {
return quickScanJson(opts, val)
}
func (opts *WindowOptsType) Value() (driver.Value, error) {
func (opts WindowOptsType) Value() (driver.Value, error) {
return quickValueJson(opts)
}
@@ -107,7 +110,7 @@ func (l *LayoutType) Scan(val interface{}) error {
return quickScanJson(l, val)
}
func (l *LayoutType) Value() (driver.Value, error) {
func (l LayoutType) Value() (driver.Value, error) {
return quickValueJson(l)
}
@@ -130,7 +133,7 @@ func (s *RemoteState) Scan(val interface{}) error {
return quickScanJson(s, val)
}
func (s *RemoteState) Value() (driver.Value, error) {
func (s RemoteState) Value() (driver.Value, error) {
return quickValueJson(s)
}
@@ -144,7 +147,7 @@ func (opts *TermOpts) Scan(val interface{}) error {
return quickScanJson(opts, val)
}
func (opts *TermOpts) Value() (driver.Value, error) {
func (opts TermOpts) Value() (driver.Value, error) {
return quickValueJson(opts)
}
+39 -20
View File
@@ -10,32 +10,47 @@ import (
type TxWrap struct {
Txx *sqlx.Tx
Err error
Ctx context.Context
}
type txWrapKey struct{}
func IsTxWrapContext(ctx context.Context) bool {
ctxVal := ctx.Value(txWrapKey{})
return ctxVal != nil
}
func WithTx(ctx context.Context, fn func(tx *TxWrap) error) (rtnErr error) {
db, err := GetDB()
if err != nil {
return err
var txWrap *TxWrap
ctxVal := ctx.Value(txWrapKey{})
if ctxVal != nil {
txWrap = ctxVal.(*TxWrap)
}
tx, beginErr := db.BeginTxx(ctx, nil)
if beginErr != nil {
return beginErr
if txWrap == nil {
db, err := GetDB(ctx)
if err != nil {
return err
}
tx, beginErr := db.BeginTxx(ctx, nil)
if beginErr != nil {
return beginErr
}
txWrap = &TxWrap{Txx: tx, Ctx: ctx}
defer func() {
if p := recover(); p != nil {
txWrap.Txx.Rollback()
panic(p)
}
if rtnErr != nil {
txWrap.Txx.Rollback()
} else {
rtnErr = txWrap.Txx.Commit()
}
}()
}
txWrap := &TxWrap{Txx: tx}
defer func() {
if p := recover(); p != nil {
tx.Rollback()
panic(p)
}
if rtnErr != nil {
tx.Rollback()
} else {
rtnErr = tx.Commit()
}
}()
fnErr := fn(txWrap)
if fnErr != nil {
return fnErr
if txWrap.Err == nil && fnErr != nil {
txWrap.Err = fnErr
}
if txWrap.Err != nil {
return txWrap.Err
@@ -43,6 +58,10 @@ func WithTx(ctx context.Context, fn func(tx *TxWrap) error) (rtnErr error) {
return nil
}
func (tx *TxWrap) Context() context.Context {
return context.WithValue(tx.Ctx, txWrapKey{}, tx)
}
func (tx *TxWrap) NamedExecWrap(query string, arg interface{}) sql.Result {
if tx.Err != nil {
return nil