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) {
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 {
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 {
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)
ctxVal := ctx.Value(historyContextKey)
if ctxVal != nil {
@ -1237,7 +1256,15 @@ func CommentCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto
if err != nil {
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 {

View File

@ -2,7 +2,6 @@ package sstore
import (
"context"
"database/sql"
"fmt"
"strconv"
"strings"
@ -16,17 +15,13 @@ const HistoryCols = "historyid, ts, userid, sessionid, screenid, windowid, linei
const DefaultMaxHistoryItems = 1000
func NumSessions(ctx context.Context) (int, error) {
db, err := GetDB(ctx)
if err != nil {
return 0, err
}
query := "SELECT count(*) FROM session"
var count int
err = db.GetContext(ctx, &count, query)
if err != nil {
return 0, err
}
return count, nil
var numSessions int
txErr := WithTx(ctx, func(tx *TxWrap) error {
query := "SELECT count(*) FROM session"
numSessions = tx.GetInt(query)
return nil
})
return numSessions, txErr
}
func GetAllRemotes(ctx context.Context) ([]*RemoteType, error) {
@ -157,17 +152,14 @@ func InsertHistoryItem(ctx context.Context, hitem *HistoryItemType) error {
if hitem == nil {
return fmt.Errorf("cannot insert nil history item")
}
db, err := GetDB(ctx)
if err != nil {
return err
}
query := `INSERT INTO history ( 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)`
_, err = db.NamedExec(query, hitem.ToMap())
if err != nil {
return err
}
return nil
txErr := WithTx(ctx, func(tx *TxWrap) error {
query := `INSERT INTO history
( 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)`
tx.NamedExecWrap(query, hitem.ToMap())
return nil
})
return txErr
}
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) {
db, err := GetDB(ctx)
if err != nil {
return nil, err
}
var sessionId string
query := `SELECT sessionid FROM session WHERE name = ?`
err = db.GetContext(ctx, &sessionId, query, name)
if err != nil {
if err == sql.ErrNoRows {
return nil, nil
var session *SessionType
txErr := WithTx(ctx, func(tx *TxWrap) error {
query := `SELECT sessionid FROM session WHERE name = ?`
sessionId := tx.GetString(query, name)
if sessionId == "" {
return 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

View File

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