This commit is contained in:
Linrador 2026-06-24 10:11:59 +02:00
parent 93e16e7f85
commit aa96f97851
5 changed files with 78 additions and 1 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -453,6 +453,28 @@ func (s *ModelStore) flushPendingStatusUpdates() error {
return nil
}
var lastErr error
for attempt := 0; attempt < 3; attempt++ {
if attempt > 0 {
time.Sleep(time.Duration(100*attempt) * time.Millisecond)
}
err := s.flushStatusUpdateBatch(lastSeen, roomState)
if err == nil {
if attempt > 0 {
appLogln("models status flush retry ok")
}
return nil
}
if !isRetryablePostgresTxError(err) {
return err
}
lastErr = err
appLogln("models status flush retry:", err)
}
return lastErr
}
func (s *ModelStore) flushStatusUpdateBatch(lastSeen map[string]modelLastSeenUpdate, roomState map[string]modelRoomStateUpdate) error {
s.mu.Lock()
defer s.mu.Unlock()
@ -540,6 +562,18 @@ WHERE lower(trim(host)) = lower(trim($7))
return tx.Commit()
}
func isRetryablePostgresTxError(err error) bool {
if err == nil {
return false
}
msg := strings.ToLower(err.Error())
return strings.Contains(msg, "sqlstate 40p01") ||
strings.Contains(msg, "deadlock") ||
strings.Contains(msg, "verklemmung") ||
strings.Contains(msg, "sqlstate 40001") ||
strings.Contains(msg, "serialization")
}
func (s *ModelStore) SetChaturbateRoomState(
host string,
modelKey string,

View File

@ -5,6 +5,7 @@ import (
"context"
"fmt"
"io"
"net"
"net/url"
"os"
"os/exec"
@ -441,7 +442,17 @@ func startLocalPostgresCluster(ctx context.Context, dataDir string, port int) er
return appErrorf("pg_ctl wurde nicht gefunden. Installiere PostgreSQL-Server-Tools oder nimm pg_ctl in PATH auf.")
}
_, _ = runLocalPostgresTool(ctx, pgCtl, "-D", dataDir, "status")
statusOut, statusErr := runLocalPostgresTool(ctx, pgCtl, "-D", dataDir, "status")
if statusErr == nil {
return nil
}
if strings.Contains(strings.ToLower(statusOut), "server is running") || strings.Contains(strings.ToLower(statusOut), "server running") {
return nil
}
if err := ensureLocalPostgresPortAvailable(port); err != nil {
return err
}
logPath := filepath.Join(dataDir, "postgresql.log")
opts := fmt.Sprintf("-p %d -h 127.0.0.1", port)
@ -452,9 +463,41 @@ func startLocalPostgresCluster(ctx context.Context, dataDir string, port int) er
if strings.Contains(strings.ToLower(out), "server is running") || strings.Contains(strings.ToLower(out), "server running") {
return nil
}
logTail := tailTextFile(logPath, 6000)
if logTail != "" {
appLogln("postgresql.log:", logTail)
return appErrorf("lokaler PostgreSQL-Server konnte nicht gestartet werden: %s\n\npostgresql.log:\n%s", out, logTail)
}
return appErrorf("lokaler PostgreSQL-Server konnte nicht gestartet werden: %s", out)
}
func ensureLocalPostgresPortAvailable(port int) error {
addr := net.JoinHostPort("127.0.0.1", strconv.Itoa(port))
conn, err := net.DialTimeout("tcp", addr, 300*time.Millisecond)
if err != nil {
return nil
}
_ = conn.Close()
return appErrorf("Port %d ist bereits belegt. Bitte in den Einstellungen einen anderen PostgreSQL-Port wählen.", port)
}
func tailTextFile(path string, maxBytes int) string {
if maxBytes <= 0 {
maxBytes = 4000
}
b, err := os.ReadFile(path)
if err != nil || len(b) == 0 {
return ""
}
if len(b) > maxBytes {
b = b[len(b)-maxBytes:]
if idx := bytes.IndexByte(b, '\n'); idx >= 0 && idx+1 < len(b) {
b = b[idx+1:]
}
}
return strings.TrimSpace(string(b))
}
func ensureLocalPostgresDatabase(ctx context.Context, port int, user, database string) error {
psql, err := postgresToolPath("psql")
if err != nil {