Files
blog/bot-go/internal/writeserver/writeserver.go
T
2026-06-01 17:57:22 +08:00

157 lines
2.8 KiB
Go

package writeserver
import (
"fmt"
"net"
"os/exec"
"path/filepath"
"sync"
"time"
)
var (
mu sync.Mutex
writeProc *exec.Cmd
writeReady bool
hugoProc *exec.Cmd
WritePort int
WriteDir string
)
func Init(writePort int, writeDir string) {
WritePort = writePort
WriteDir = writeDir
}
func StartWriteServer() map[string]interface{} {
mu.Lock()
defer mu.Unlock()
if writeProc != nil {
if writeReady {
return map[string]interface{}{"started": false, "reason": "already_running"}
}
return map[string]interface{}{"started": false, "reason": "starting"}
}
writeReady = false
writeProc = exec.Command(filepath.Join(WriteDir, "writeserver.exe"))
writeProc.Dir = WriteDir
if err := writeProc.Start(); err != nil {
writeProc = nil
return map[string]interface{}{"started": false, "reason": err.Error()}
}
writeReady = true
go func() {
err := writeProc.Wait()
mu.Lock()
defer mu.Unlock()
fmt.Printf("[write] exited: %v\n", err)
writeProc = nil
writeReady = false
}()
return map[string]interface{}{"started": true}
}
func StopWriteServer() bool {
mu.Lock()
defer mu.Unlock()
if hugoProc != nil {
killProcessTree(hugoProc)
hugoProc = nil
}
if writeProc == nil {
return false
}
killProcessTree(writeProc)
writeProc = nil
writeReady = false
return true
}
func killProcessTree(cmd *exec.Cmd) {
if cmd == nil || cmd.Process == nil {
return
}
// On Windows, use taskkill /T to kill process tree
pid := cmd.Process.Pid
killCmd := exec.Command("taskkill", "/PID", fmt.Sprintf("%d", pid), "/T", "/F")
killCmd.Run()
cmd.Process.Kill()
}
func StartHugoIfNeeded() {
mu.Lock()
defer mu.Unlock()
if hugoProc != nil {
return
}
hugoDir := WriteDir + "/.."
hugoProc = exec.Command("hugo", "server", "--bind", "0.0.0.0", "--port", "1313", "--disableFastRender")
hugoProc.Dir = hugoDir
if err := hugoProc.Start(); err != nil {
fmt.Printf("[hugo] start error: %v\n", err)
hugoProc = nil
return
}
fmt.Println("[hugo] started on 0.0.0.0:1313")
go func() {
err := hugoProc.Wait()
mu.Lock()
defer mu.Unlock()
fmt.Printf("[hugo] exited: %v\n", err)
hugoProc = nil
}()
}
func GetWriteStatus() map[string]interface{} {
mu.Lock()
running := writeProc != nil && writeReady
starting := writeProc != nil && !writeReady
mu.Unlock()
// Also check via TCP if we are not tracking a process
if !running && !starting {
conn, err := net.DialTimeout("tcp", fmt.Sprintf("127.0.0.1:%d", WritePort), 2*time.Second)
if err == nil {
conn.Close()
running = true
}
}
return map[string]interface{}{
"running": running,
"starting": starting,
}
}
func SetWriteReady(ready bool) {
mu.Lock()
defer mu.Unlock()
writeReady = ready
}
func IsWriteReady() bool {
mu.Lock()
defer mu.Unlock()
return writeReady
}
func IsWriteRunning() bool {
mu.Lock()
defer mu.Unlock()
return writeProc != nil
}