fix(backend): concurrent map writes

This commit is contained in:
pycook
2025-03-05 21:23:41 +08:00
parent 57291e6737
commit 9d77450ffb
2 changed files with 53 additions and 7 deletions

View File

@@ -36,7 +36,6 @@ func initDB() {
logger.L().Fatal("Failed to drop index", zap.Error(err)) logger.L().Fatal("Failed to drop index", zap.Error(err))
} }
defer db.Close()
} }
func RunApi() error { func RunApi() error {

View File

@@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"strings" "strings"
"sync"
"github.com/samber/lo" "github.com/samber/lo"
"github.com/veops/go-ansiterm" "github.com/veops/go-ansiterm"
@@ -46,6 +47,7 @@ func NewParser(sessionId string, w, h int) *Parser {
OutputStream: stream, OutputStream: stream,
isEdit: false, isEdit: false,
isPrompt: true, isPrompt: true,
mu: &sync.Mutex{},
} }
return p return p
} }
@@ -63,12 +65,16 @@ type Parser struct {
lastCmd string lastCmd string
lastRes string lastRes string
curRes string curRes string
mu *sync.Mutex
} }
func (p *Parser) AddInput(bs []byte) (cmd string, forbidden bool) { func (p *Parser) AddInput(bs []byte) (cmd string, forbidden bool) {
p.mu.Lock()
defer p.mu.Unlock()
if p.isPrompt && !p.isEdit { if p.isPrompt && !p.isEdit {
//TODO: may someone has empty ps1? //TODO: may someone has empty ps1?
if ps1 := p.GetOutput(); ps1 != "" { if ps1 := p.getOutputLocked(); ps1 != "" {
p.prompt = ps1 p.prompt = ps1
} }
p.isPrompt = false p.isPrompt = false
@@ -81,7 +87,7 @@ func (p *Parser) AddInput(bs []byte) (cmd string, forbidden bool) {
return return
} }
p.isPrompt = true p.isPrompt = true
p.curCmd = p.GetCmd() p.curCmd = p.getCmdLocked()
p.Reset() p.Reset()
filter := "" filter := ""
if filter, forbidden = p.IsForbidden(p.curCmd); forbidden { if filter, forbidden = p.IsForbidden(p.curCmd); forbidden {
@@ -126,34 +132,72 @@ func (p *Parser) WriteDb() {
} }
func (p *Parser) Close(prompt string) { func (p *Parser) Close(prompt string) {
p.mu.Lock()
defer p.mu.Unlock()
if prompt == "" { if prompt == "" {
prompt = p.prompt prompt = p.prompt
} }
p.AddOutput([]byte("\r\n" + prompt)) p.AddOutputLocked([]byte("\r\n" + prompt))
p.AddInput([]byte("\r")) p.AddInputLocked([]byte("\r"))
} }
func (p *Parser) AddOutput(bs []byte) { func (p *Parser) AddOutput(bs []byte) {
p.mu.Lock()
defer p.mu.Unlock()
p.AddOutputLocked(bs)
}
func (p *Parser) AddOutputLocked(bs []byte) {
p.Output = append(p.Output, bs...) p.Output = append(p.Output, bs...)
} }
func (p *Parser) AddInputLocked(bs []byte) {
p.Input = append(p.Input, bs...)
}
func (p *Parser) GetCmd() string { func (p *Parser) GetCmd() string {
s := p.GetOutput() p.mu.Lock()
defer p.mu.Unlock()
return p.getCmdLocked()
}
func (p *Parser) getCmdLocked() string {
s := p.getOutputLocked()
// TODO: some promot may change with its dir // TODO: some promot may change with its dir
return strings.TrimPrefix(s, p.prompt) return strings.TrimPrefix(s, p.prompt)
} }
func (p *Parser) Resize(w, h int) { func (p *Parser) Resize(w, h int) {
p.mu.Lock()
defer p.mu.Unlock()
p.OutputStream.Listener.Resize(w, h) p.OutputStream.Listener.Resize(w, h)
} }
func (p *Parser) Reset() { func (p *Parser) Reset() {
p.mu.Lock()
defer p.mu.Unlock()
p.resetLocked()
}
func (p *Parser) resetLocked() {
p.OutputStream.Listener.Reset() p.OutputStream.Listener.Reset()
p.Output = nil p.Output = nil
p.Input = nil p.Input = nil
} }
func (p *Parser) GetOutput() string { func (p *Parser) GetOutput() string {
p.mu.Lock()
defer p.mu.Unlock()
return p.getOutputLocked()
}
func (p *Parser) getOutputLocked() string {
p.OutputStream.Feed(p.Output) p.OutputStream.Feed(p.Output)
res := p.OutputStream.Listener.Display() res := p.OutputStream.Listener.Display()
@@ -172,13 +216,16 @@ func (p *Parser) GetOutput() string {
} }
func (p *Parser) State(b []byte) bool { func (p *Parser) State(b []byte) bool {
p.mu.Lock()
defer p.mu.Unlock()
if !p.isEdit && IsEditEnterMode(b) { if !p.isEdit && IsEditEnterMode(b) {
if !isNewScreen(b) { if !isNewScreen(b) {
p.isEdit = true p.isEdit = true
} }
} }
if p.isEdit && IsEditExitMode(b) { if p.isEdit && IsEditExitMode(b) {
p.Reset() p.resetLocked()
p.isEdit = false p.isEdit = false
} }
return p.isEdit return p.isEdit