single-thread DB access. send selectedline updates for run/comment commands

This commit is contained in:
sawka 2022-10-10 17:30:48 -07:00
parent 43cf55b25e
commit d19f29c467
3 changed files with 68 additions and 38 deletions

View File

@ -217,7 +217,7 @@ func resolveNonNegInt(arg string, def int) (int, error) {
} }
func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_RemoteConnected) ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window|R_RemoteConnected)
if err != nil { if err != nil {
return nil, fmt.Errorf("/run error: %w", err) return nil, fmt.Errorf("/run error: %w", err)
} }
@ -252,7 +252,26 @@ func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.U
if err != nil { if err != nil {
return nil, err return nil, err
} }
update := sstore.ModelUpdate{Line: rtnLine, Cmd: cmd, Interactive: pk.Interactive} sw, err := sstore.GetScreenWindowByIds(ctx, ids.SessionId, ids.ScreenId, ids.WindowId)
if err != nil {
// ignore error here, because the command has already run (nothing to do)
fmt.Printf("/run error getting screen-window: %v\n", err)
}
if sw != nil {
updateMap := make(map[string]interface{})
updateMap[sstore.SWField_SelectedLine] = rtnLine.LineNum
sw, err = sstore.UpdateScreenWindow(ctx, ids.SessionId, ids.ScreenId, ids.WindowId, updateMap)
if err != nil {
// ignore error again (nothing to do)
fmt.Printf("/run error updating screen-window selected line: %v\n", err)
}
}
update := sstore.ModelUpdate{
Line: rtnLine,
Cmd: cmd,
ScreenWindow: sw,
Interactive: pk.Interactive,
}
sstore.MainBus.SendUpdate(ids.SessionId, update) sstore.MainBus.SendUpdate(ids.SessionId, update)
ctxVal := ctx.Value(historyContextKey) ctxVal := ctx.Value(historyContextKey)
if ctxVal != nil { if ctxVal != nil {
@ -1237,7 +1256,15 @@ func CommentCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto
if err != nil { if err != nil {
return nil, err return nil, err
} }
return sstore.ModelUpdate{Line: rtnLine}, nil updateMap := make(map[string]interface{})
updateMap[sstore.SWField_SelectedLine] = rtnLine.LineNum
sw, err := sstore.UpdateScreenWindow(ctx, ids.SessionId, ids.ScreenId, ids.WindowId, updateMap)
if err != nil {
// ignore error again (nothing to do)
fmt.Printf("/comment error updating screen-window selected line: %v\n", err)
}
update := sstore.ModelUpdate{Line: rtnLine, ScreenWindow: sw}
return update, nil
} }
func maybeQuote(s string, quote bool) string { func maybeQuote(s string, quote bool) string {

View File

@ -2,7 +2,6 @@ package sstore
import ( import (
"context" "context"
"database/sql"
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
@ -16,17 +15,13 @@ const HistoryCols = "historyid, ts, userid, sessionid, screenid, windowid, linei
const DefaultMaxHistoryItems = 1000 const DefaultMaxHistoryItems = 1000
func NumSessions(ctx context.Context) (int, error) { func NumSessions(ctx context.Context) (int, error) {
db, err := GetDB(ctx) var numSessions int
if err != nil { txErr := WithTx(ctx, func(tx *TxWrap) error {
return 0, err query := "SELECT count(*) FROM session"
} numSessions = tx.GetInt(query)
query := "SELECT count(*) FROM session" return nil
var count int })
err = db.GetContext(ctx, &count, query) return numSessions, txErr
if err != nil {
return 0, err
}
return count, nil
} }
func GetAllRemotes(ctx context.Context) ([]*RemoteType, error) { func GetAllRemotes(ctx context.Context) ([]*RemoteType, error) {
@ -157,17 +152,14 @@ func InsertHistoryItem(ctx context.Context, hitem *HistoryItemType) error {
if hitem == nil { if hitem == nil {
return fmt.Errorf("cannot insert nil history item") return fmt.Errorf("cannot insert nil history item")
} }
db, err := GetDB(ctx) txErr := WithTx(ctx, func(tx *TxWrap) error {
if err != nil { query := `INSERT INTO history
return err ( historyid, ts, userid, sessionid, screenid, windowid, lineid, cmdid, haderror, cmdstr, remoteownerid, remoteid, remotename, ismetacmd) VALUES
} (:historyid,:ts,:userid,:sessionid,:screenid,:windowid,:lineid,:cmdid,:haderror,:cmdstr,:remoteownerid,:remoteid,:remotename,:ismetacmd)`
query := `INSERT INTO history ( historyid, ts, userid, sessionid, screenid, windowid, lineid, cmdid, haderror, cmdstr, remoteownerid, remoteid, remotename, ismetacmd) VALUES tx.NamedExecWrap(query, hitem.ToMap())
(:historyid,:ts,:userid,:sessionid,:screenid,:windowid,:lineid,:cmdid,:haderror,:cmdstr,:remoteownerid,:remoteid,:remotename,:ismetacmd)` return nil
_, err = db.NamedExec(query, hitem.ToMap()) })
if err != nil { return txErr
return err
}
return nil
} }
func runHistoryQuery(tx *TxWrap, sessionId string, windowId string, opts HistoryQueryOpts) ([]*HistoryItemType, error) { func runHistoryQuery(tx *TxWrap, sessionId string, windowId string, opts HistoryQueryOpts) ([]*HistoryItemType, error) {
@ -372,20 +364,24 @@ func GetSessionById(ctx context.Context, id string) (*SessionType, error) {
} }
func GetSessionByName(ctx context.Context, name string) (*SessionType, error) { func GetSessionByName(ctx context.Context, name string) (*SessionType, error) {
db, err := GetDB(ctx) var session *SessionType
if err != nil { txErr := WithTx(ctx, func(tx *TxWrap) error {
return nil, err query := `SELECT sessionid FROM session WHERE name = ?`
} sessionId := tx.GetString(query, name)
var sessionId string if sessionId == "" {
query := `SELECT sessionid FROM session WHERE name = ?` return nil
err = db.GetContext(ctx, &sessionId, query, name)
if err != nil {
if err == sql.ErrNoRows {
return nil, nil
} }
return nil, err var err error
session, err = GetSessionById(tx.Context(), sessionId)
if err != nil {
return err
}
return nil
})
if txErr != nil {
return nil, txErr
} }
return GetSessionById(ctx, sessionId) return session, nil
} }
// also creates default window, returns sessionId // also creates default window, returns sessionId

View File

@ -3,6 +3,7 @@ package sstore
import ( import (
"context" "context"
"database/sql" "database/sql"
"sync"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
) )
@ -15,6 +16,9 @@ type TxWrap struct {
type txWrapKey struct{} type txWrapKey struct{}
// single-threaded access to DB
var globalNestingLock = &sync.Mutex{}
func IsTxWrapContext(ctx context.Context) bool { func IsTxWrapContext(ctx context.Context) bool {
ctxVal := ctx.Value(txWrapKey{}) ctxVal := ctx.Value(txWrapKey{})
return ctxVal != nil return ctxVal != nil
@ -30,6 +34,9 @@ func WithTx(ctx context.Context, fn func(tx *TxWrap) error) (rtnErr error) {
} }
} }
if txWrap == nil { if txWrap == nil {
globalNestingLock.Lock()
defer globalNestingLock.Unlock()
db, err := GetDB(ctx) db, err := GetDB(ctx)
if err != nil { if err != nil {
return err return err