mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-22 16:48:23 +01:00
checkpoint on storing cmd in db
This commit is contained in:
parent
d4acb79585
commit
f7666fe480
@ -459,12 +459,15 @@ func ProcessFeCommandPacket(ctx context.Context, pk *scpacket.FeCommandPacketTyp
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
startPk, err := remote.RunCommand(ctx, pk, rtnLine.CmdId)
|
cmd, err := remote.RunCommand(ctx, pk, rtnLine.CmdId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
fmt.Printf("START CMD: %s\n", packet.AsString(startPk))
|
err = sstore.InsertCmd(ctx, cmd)
|
||||||
return &runCommandResponse{Line: rtnLine}, nil
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &runCommandResponse{Line: rtnLine, Cmd: cmd}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// /api/start-session
|
// /api/start-session
|
||||||
|
@ -3,5 +3,5 @@ DROP TABLE window;
|
|||||||
DROP TABLE remote_instance;
|
DROP TABLE remote_instance;
|
||||||
DROP TABLE line;
|
DROP TABLE line;
|
||||||
DROP TABLE remote;
|
DROP TABLE remote;
|
||||||
DROP TABLE session_cmd;
|
DROP TABLE cmd;
|
||||||
DROP TABLE history;
|
DROP TABLE history;
|
||||||
|
@ -52,18 +52,17 @@ CREATE TABLE remote (
|
|||||||
lastconnectts bigint NOT NULL
|
lastconnectts bigint NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE session_cmd (
|
CREATE TABLE cmd (
|
||||||
sessionid varchar(36) NOT NULL,
|
sessionid varchar(36) NOT NULL,
|
||||||
cmdid varchar(36) NOT NULL,
|
cmdid varchar(36) NOT NULL,
|
||||||
rsid varchar(36) NOT NULL,
|
|
||||||
remoteid varchar(36) NOT NULL,
|
remoteid varchar(36) NOT NULL,
|
||||||
|
cmdstr text NOT NULL,
|
||||||
remotestate json NOT NULL,
|
remotestate json NOT NULL,
|
||||||
|
termopts json NOT NULL,
|
||||||
status varchar(10) NOT NULL,
|
status varchar(10) NOT NULL,
|
||||||
startts bigint NOT NULL,
|
startpk json NOT NULL,
|
||||||
pid int NOT NULL,
|
donepk json NOT NULL,
|
||||||
runnerpid int NOT NULL,
|
runout json NOT NULL,
|
||||||
donets bigint NOT NULL,
|
|
||||||
exitcode int NOT NULL,
|
|
||||||
PRIMARY KEY (sessionid, cmdid)
|
PRIMARY KEY (sessionid, cmdid)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -154,7 +154,15 @@ func (msh *MShellProc) IsConnected() bool {
|
|||||||
return msh.Status == StatusConnected
|
return msh.Status == StatusConnected
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType, cmdId string) (*packet.CmdStartPacketType, error) {
|
func convertRemoteState(rs scpacket.RemoteState) sstore.RemoteState {
|
||||||
|
return sstore.RemoteState{Cwd: rs.Cwd}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeTermOpts() sstore.TermOpts {
|
||||||
|
return sstore.TermOpts{Rows: DefaultTermRows, Cols: DefaultTermCols, FlexRows: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType, cmdId string) (*sstore.CmdType, error) {
|
||||||
msh := GetRemoteById(pk.RemoteState.RemoteId)
|
msh := GetRemoteById(pk.RemoteState.RemoteId)
|
||||||
if msh == nil {
|
if msh == nil {
|
||||||
return nil, fmt.Errorf("no remote id=%s found", pk.RemoteState.RemoteId)
|
return nil, fmt.Errorf("no remote id=%s found", pk.RemoteState.RemoteId)
|
||||||
@ -177,15 +185,29 @@ func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType, cmdId str
|
|||||||
return nil, fmt.Errorf("sending run packet to remote: %w", err)
|
return nil, fmt.Errorf("sending run packet to remote: %w", err)
|
||||||
}
|
}
|
||||||
rtnPk := msh.ServerProc.Output.WaitForResponse(ctx, runPacket.ReqId)
|
rtnPk := msh.ServerProc.Output.WaitForResponse(ctx, runPacket.ReqId)
|
||||||
if startPk, ok := rtnPk.(*packet.CmdStartPacketType); ok {
|
startPk, ok := rtnPk.(*packet.CmdStartPacketType)
|
||||||
return startPk, nil
|
if !ok {
|
||||||
}
|
respPk, ok := rtnPk.(*packet.ResponsePacketType)
|
||||||
if respPk, ok := rtnPk.(*packet.ResponsePacketType); ok {
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("invalid response received from server for run packet: %s", packet.AsString(rtnPk))
|
||||||
|
}
|
||||||
if respPk.Error != "" {
|
if respPk.Error != "" {
|
||||||
return nil, errors.New(respPk.Error)
|
return nil, errors.New(respPk.Error)
|
||||||
}
|
}
|
||||||
|
return nil, fmt.Errorf("invalid response received from server for run packet: %s", packet.AsString(rtnPk))
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("invalid response received from server for run packet: %s", packet.AsString(rtnPk))
|
cmd := &sstore.CmdType{
|
||||||
|
SessionId: pk.SessionId,
|
||||||
|
CmdId: startPk.CK.GetCmdId(),
|
||||||
|
RemoteId: msh.Remote.RemoteId,
|
||||||
|
RemoteState: convertRemoteState(pk.RemoteState),
|
||||||
|
TermOpts: makeTermOpts(),
|
||||||
|
Status: "running",
|
||||||
|
StartPk: startPk,
|
||||||
|
DonePk: nil,
|
||||||
|
RunOut: nil,
|
||||||
|
}
|
||||||
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msh *MShellProc) PacketRpc(ctx context.Context, pk packet.RpcPacketType) (*packet.ResponsePacketType, error) {
|
func (msh *MShellProc) PacketRpc(ctx context.Context, pk packet.RpcPacketType) (*packet.ResponsePacketType, error) {
|
||||||
|
@ -103,6 +103,11 @@ func GetSessionById(ctx context.Context, id string) (*SessionType, error) {
|
|||||||
tx.SelectWrap(&session.Windows, query, session.SessionId)
|
tx.SelectWrap(&session.Windows, query, session.SessionId)
|
||||||
query = `SELECT * FROM remote_instance WHERE sessionid = ?`
|
query = `SELECT * FROM remote_instance WHERE sessionid = ?`
|
||||||
tx.SelectWrap(&session.Remotes, query, session.SessionId)
|
tx.SelectWrap(&session.Remotes, query, session.SessionId)
|
||||||
|
query = `SELECT * FROM cmd WHERE sessionid = ?`
|
||||||
|
marr := tx.SelectMaps(query, session.SessionId)
|
||||||
|
for _, m := range marr {
|
||||||
|
session.Cmds = append(session.Cmds, CmdFromMap(m))
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -191,3 +196,41 @@ func InsertLine(ctx context.Context, line *LineType) error {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func InsertCmd(ctx context.Context, cmd *CmdType) error {
|
||||||
|
if cmd == nil {
|
||||||
|
return fmt.Errorf("cmd cannot be nil")
|
||||||
|
}
|
||||||
|
return WithTx(ctx, func(tx *TxWrap) error {
|
||||||
|
var sessionId string
|
||||||
|
query := `SELECT sessionid FROM session WHERE sessionid = ?`
|
||||||
|
hasSession := tx.GetWrap(&sessionId, query, cmd.SessionId)
|
||||||
|
if !hasSession {
|
||||||
|
return fmt.Errorf("session not found, cannot insert cmd")
|
||||||
|
}
|
||||||
|
cmdMap := cmd.ToMap()
|
||||||
|
query = `
|
||||||
|
INSERT INTO cmd ( sessionid, cmdid, remoteid, cmdstr, remotestate, termopts, status, startpk, donepk, runout)
|
||||||
|
VALUES (:sessionid,:cmdid,:remoteid,:cmdstr,:remotestate,:termopts,:status,:startpk,:donepk,:runout)
|
||||||
|
`
|
||||||
|
tx.NamedExecWrap(query, cmdMap)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCmd(ctx context.Context, sessionId string, cmdId string) (*CmdType, error) {
|
||||||
|
db, err := GetDB()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var m map[string]interface{}
|
||||||
|
query := `SELECT * FROM cmd WHERE sessionid = ? AND cmdid = ?`
|
||||||
|
err = db.GetContext(ctx, &m, query, sessionId, cmdId)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return CmdFromMap(m), nil
|
||||||
|
}
|
||||||
|
@ -89,6 +89,30 @@ func (s *RemoteState) Value() (driver.Value, error) {
|
|||||||
return json.Marshal(s)
|
return json.Marshal(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TermOpts struct {
|
||||||
|
Rows int `json:"rows"`
|
||||||
|
Cols int `json:"cols"`
|
||||||
|
FlexRows bool `json:"flexrows,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opts *TermOpts) Scan(val interface{}) error {
|
||||||
|
if strVal, ok := val.(string); ok {
|
||||||
|
if strVal == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := json.Unmarshal([]byte(strVal), opts)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("cannot scan '%T' into TermOpts", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opts *TermOpts) Value() (driver.Value, error) {
|
||||||
|
return json.Marshal(opts)
|
||||||
|
}
|
||||||
|
|
||||||
type RemoteInstance struct {
|
type RemoteInstance struct {
|
||||||
RIId string `json:"riid"`
|
RIId string `json:"riid"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@ -127,19 +151,81 @@ type RemoteType struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type CmdType struct {
|
type CmdType struct {
|
||||||
SessionId string `json:"sessionid"`
|
SessionId string `json:"sessionid"`
|
||||||
CmdId string `json:"cmdid"`
|
CmdId string `json:"cmdid"`
|
||||||
RSId string `json:"rsid"`
|
RemoteId string `json:"remoteid"`
|
||||||
RemoteId string `json:"remoteid"`
|
CmdStr string `json:"cmdstr"`
|
||||||
RemoteState string `json:"remotestate"`
|
RemoteState RemoteState `json:"remotestate"`
|
||||||
Status string `json:"status"`
|
TermOpts TermOpts `json:"termopts"`
|
||||||
StartTs int64 `json:"startts"`
|
Status string `json:"status"`
|
||||||
DoneTs int64 `json:"donets"`
|
StartPk *packet.CmdStartPacketType `json:"startpk"`
|
||||||
Pid int `json:"pid"`
|
DonePk *packet.CmdDonePacketType `json:"donepk"`
|
||||||
RunnerPid int `json:"runnerpid"`
|
RunOut []packet.PacketType `json:"runout"`
|
||||||
ExitCode int `json:"exitcode"`
|
}
|
||||||
|
|
||||||
RunOut packet.PacketType `json:"runout"`
|
func quickJson(v interface{}) string {
|
||||||
|
if v == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
barr, _ := json.Marshal(v)
|
||||||
|
return string(barr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *CmdType) ToMap() map[string]interface{} {
|
||||||
|
rtn := make(map[string]interface{})
|
||||||
|
rtn["sessionid"] = cmd.SessionId
|
||||||
|
rtn["cmdid"] = cmd.CmdId
|
||||||
|
rtn["remoteid"] = cmd.RemoteId
|
||||||
|
rtn["cmdstr"] = cmd.CmdStr
|
||||||
|
rtn["remotestate"] = quickJson(cmd.RemoteState)
|
||||||
|
rtn["termopts"] = quickJson(cmd.TermOpts)
|
||||||
|
rtn["status"] = cmd.Status
|
||||||
|
rtn["startpk"] = quickJson(cmd.StartPk)
|
||||||
|
rtn["donepk"] = quickJson(cmd.DonePk)
|
||||||
|
rtn["runout"] = quickJson(cmd.RunOut)
|
||||||
|
return rtn
|
||||||
|
}
|
||||||
|
|
||||||
|
func quickSetStr(strVal *string, m map[string]interface{}, name string) {
|
||||||
|
v, ok := m[name]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
str, ok := v.(string)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
*strVal = str
|
||||||
|
}
|
||||||
|
|
||||||
|
func quickSetJson(ptr interface{}, m map[string]interface{}, name string) {
|
||||||
|
v, ok := m[name]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
str, ok := v.(string)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if str == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
json.Unmarshal([]byte(str), ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CmdFromMap(m map[string]interface{}) *CmdType {
|
||||||
|
var cmd CmdType
|
||||||
|
quickSetStr(&cmd.SessionId, m, "sessionid")
|
||||||
|
quickSetStr(&cmd.CmdId, m, "cmdid")
|
||||||
|
quickSetStr(&cmd.RemoteId, m, "remoteid")
|
||||||
|
quickSetStr(&cmd.CmdStr, m, "cmdstr")
|
||||||
|
quickSetJson(&cmd.RemoteState, m, "remotestate")
|
||||||
|
quickSetJson(&cmd.TermOpts, m, "termopts")
|
||||||
|
quickSetStr(&cmd.Status, m, "status")
|
||||||
|
quickSetJson(&cmd.StartPk, m, "startpk")
|
||||||
|
quickSetJson(&cmd.DonePk, m, "donepk")
|
||||||
|
quickSetJson(&cmd.RunOut, m, "runout")
|
||||||
|
return &cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeNewLineCmd(sessionId string, windowId string, userId string) *LineType {
|
func makeNewLineCmd(sessionId string, windowId string, userId string) *LineType {
|
||||||
|
@ -90,3 +90,25 @@ func (tx *TxWrap) SelectWrap(dest interface{}, query string, args ...interface{}
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tx *TxWrap) SelectMaps(query string, args ...interface{}) []map[string]interface{} {
|
||||||
|
if tx.Err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
rows, err := tx.Txx.Queryx(query, args...)
|
||||||
|
if err != nil {
|
||||||
|
tx.Err = err
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var rtn []map[string]interface{}
|
||||||
|
for rows.Next() {
|
||||||
|
m := make(map[string]interface{})
|
||||||
|
err = rows.MapScan(m)
|
||||||
|
if err != nil {
|
||||||
|
tx.Err = err
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
rtn = append(rtn, m)
|
||||||
|
}
|
||||||
|
return rtn
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user