feat: start configured agent server

This commit is contained in:
2026-09-02 06:10:14 +00:00
parent 083cca1ce7
commit 92617a2400
2 changed files with 90 additions and 4 deletions
+90 -1
View File
@@ -1,4 +1,93 @@
// Command rvbox-server is the RVBox control and agent server.
package main
func main() {}
import (
"context"
"errors"
"flag"
"fmt"
"log"
"net"
"net/http"
"os"
"os/signal"
"syscall"
"github.com/rvbox/rvbox/internal/agentproto"
"github.com/rvbox/rvbox/internal/config"
"github.com/rvbox/rvbox/internal/server/session"
"github.com/rvbox/rvbox/internal/server/store"
)
func main() {
var configPath string
flag.StringVar(&configPath, "config", "", "absolute server TOML configuration path")
flag.Parse()
if configPath == "" {
log.Print("rvbox-server: --config is required")
os.Exit(2)
}
if err := run(configPath); err != nil {
log.Printf("rvbox-server: %v", err)
os.Exit(1)
}
}
func run(configPath string) error {
configured, err := config.LoadServer(configPath)
if err != nil {
return err
}
persistence, err := store.Open(context.Background(), store.Options{
DataDir: configured.Server.DataDir, BusyTimeout: configured.Storage.SQLiteBusyTimeout,
SegmentTargetSize: configured.Storage.SegmentTargetBytes,
QuotaLimits: store.QuotaLimits{
HardAllocationBytes: store.DefaultSegmentLimit,
CommandOutputBytes: configured.Storage.CommandOutputLimitBytes,
CommandTotalBytes: configured.Storage.CommandTotalLimitBytes,
ClientTotalBytes: configured.Storage.ClientTotalLimitBytes,
ServerTotalBytes: configured.Storage.ServerTotalLimitBytes,
CloseoutReserveBytes: configured.Storage.CommandCloseoutReserveBytes,
FilesystemFloorBytes: configured.Storage.FreeSpaceFloorBytes,
},
})
if err != nil {
return err
}
defer persistence.Close()
listener, err := net.Listen("tcp", configured.Server.AgentListen)
if err != nil {
return fmt.Errorf("listen for agents: %w", err)
}
agent := &session.AgentServer{
Store: persistence, Registry: session.NewRegistry(), Path: configured.Server.AgentPath,
Limits: agentproto.Limits{
MaxEnvelopeBytes: configured.Protocol.MaxAgentEnvelopeBytes,
MaxExecutionSpecBytes: configured.Protocol.MaxExecutionSpecBytes,
MaxRawChunkBytes: configured.Protocol.MaxRawChunkBytes,
MaxScriptBytes: configured.Protocol.MaxScriptBytes,
MaxDetailBytes: configured.Storage.ProtocolDetailMaxBytes,
},
WriteDeadline: configured.Flow.WriteDeadline,
HeartbeatIdle: configured.Protocol.HeartbeatIdle, LivenessTimeout: configured.Protocol.LivenessTimeout,
}
httpServer := &http.Server{Handler: agent, ReadHeaderTimeout: configured.Flow.WriteDeadline}
serveError := make(chan error, 1)
go func() { serveError <- httpServer.Serve(listener) }()
signals := make(chan os.Signal, 1)
signal.Notify(signals, os.Interrupt, syscall.SIGTERM)
defer signal.Stop(signals)
select {
case err := <-serveError:
if errors.Is(err, http.ErrServerClosed) {
return nil
}
return err
case <-signals:
shutdownContext, cancel := context.WithTimeout(context.Background(), configured.Server.ShutdownGrace)
defer cancel()
return httpServer.Shutdown(shutdownContext)
}
}