removed device_id from all entities except car. Replaced with car_id . Car -> device_id

This commit is contained in:
2026-07-16 17:40:59 +04:00
parent 41eaf49bb2
commit f6547cd1f1
18 changed files with 126 additions and 78 deletions
+5 -2
View File
@@ -189,6 +189,7 @@ func carToWire(c catalog.CarMeta) transport.CarWire {
ColorHex: c.ColorHex,
AvatarURL: c.AvatarURL,
Active: c.Active,
DeviceID: c.DeviceID,
// Stats are read-mostly; the server fills them on read.
TotalDistanceM: c.TotalDistanceM,
TotalRaces: c.TotalRaces,
@@ -239,8 +240,9 @@ func carFromWire(w transport.CarWire) catalog.CarMeta {
ColorHex: w.ColorHex,
AvatarURL: w.AvatarURL,
Active: w.Active,
CreatedMs: w.CreatedMs,
UpdatedMs: w.UpdatedMs,
CreatedMs: w.CreatedMs,
UpdatedMs: w.UpdatedMs,
DeviceID: w.DeviceID,
}
}
@@ -292,6 +294,7 @@ func carPatchFromWire(p transport.CarPatch) catalog.UpdateCarOptions {
Chassis: chassisFromPtr(p.Chassis),
Motor: motorFromPtr(p.Motor),
Battery: batteryFromPtr(p.Battery),
DeviceID: p.DeviceID,
}
}
+15 -18
View File
@@ -283,7 +283,7 @@ func driversListHandler(svc *drivers.Service) http.HandlerFunc {
// @Router /api/drivers/{id} [get]
// @Router /api/drivers/{id} [put]
// @Router /api/drivers/{id} [delete]
// @Router /api/drivers/{id}/device [put]
// @Router /api/drivers/{id}/car [put]
func driversByIDHandler(svc *drivers.Service, lobbySvc *lobby.Service) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id := strings.TrimPrefix(r.URL.Path, "/api/drivers/")
@@ -291,8 +291,8 @@ func driversByIDHandler(svc *drivers.Service, lobbySvc *lobby.Service) http.Hand
writeError(w, http.StatusBadRequest, "bad_request", "missing driver id")
return
}
if strings.HasSuffix(id, "/device") {
driverID := strings.TrimSuffix(id, "/device")
if strings.HasSuffix(id, "/car") {
driverID := strings.TrimSuffix(id, "/car")
if driverID == "" {
writeError(w, http.StatusBadRequest, "bad_request", "missing driver id")
return
@@ -303,29 +303,26 @@ func driversByIDHandler(svc *drivers.Service, lobbySvc *lobby.Service) http.Hand
return
}
// Read device_id from JSON body or query param
var deviceID *int
type deviceRequest struct {
DeviceID *int `json:"device_id"`
// Read car_id from JSON body or query param
var carID *string
type carRequest struct {
CarID *string `json:"car_id"`
}
var req deviceRequest
var req carRequest
if r.ContentLength > 0 {
if err := json.NewDecoder(r.Body).Decode(&req); err == nil {
deviceID = req.DeviceID
carID = req.CarID
}
}
// Fallback to query parameter if body didn't provide it
if deviceID == nil {
qVal := r.URL.Query().Get("device_id")
if carID == nil {
qVal := r.URL.Query().Get("car_id")
if qVal != "" {
if qVal == "null" {
deviceID = nil
} else if idInt, err := strconv.Atoi(qVal); err == nil {
deviceID = &idInt
carID = nil
} else {
writeError(w, http.StatusBadRequest, "bad_request", "invalid device_id query parameter")
return
carID = &qVal
}
}
}
@@ -345,8 +342,8 @@ func driversByIDHandler(svc *drivers.Service, lobbySvc *lobby.Service) http.Hand
_, _ = lobbySvc.AddDriver(driverID, drv.Name, "")
lobbySvc.SetDriverProfile(driverID, drv.Nickname, drv.AvatarURL, drv.ClanID, "")
// Select device in lobby (handles constraints and write-through)
if err := lobbySvc.SelectDevice(driverID, deviceID); err != nil {
// Select car in lobby (handles constraints and write-through)
if err := lobbySvc.SelectCar(driverID, carID); err != nil {
writeError(w, http.StatusBadRequest, "bad_request", err.Error())
return
}
+7 -5
View File
@@ -199,7 +199,7 @@ func main() {
driversSvc := drivers.NewService(drivers.NewPgStore(pool))
// WebRTC 1-to-1 driver-car proxy service
webrtcSvc := NewWebRTCService(logger, engine, lobbySvc, videoSvc)
webrtcSvc := NewWebRTCService(logger, engine, lobbySvc, videoSvc, cat)
// Persist finished races so the /api/races list and keyset pagination
// can serve historical data across restarts. The snapshot is best-
@@ -577,7 +577,7 @@ func readPump(cfg *config.Config, c *realtime.Client, conn *websocket.Conn, e *c
case transport.TypeClientHello:
handleClientHello(c, e, cfg, lobbySvc, driversSvc, env)
case transport.TypeJoinRace:
handleJoinRace(c, e, lobbySvc, env)
handleJoinRace(c, e, lobbySvc, cat, env)
case transport.TypeLeaveRace:
handleLeaveRace(c, e, env)
case transport.TypeInputState:
@@ -635,7 +635,7 @@ func handleClientHello(c *realtime.Client, e *control.Engine, cfg *config.Config
c.Send <- mustEncode(transport.TypeServerHello, hello)
}
func handleJoinRace(c *realtime.Client, e *control.Engine, lobbySvc *lobby.Service, env *transport.Envelope) {
func handleJoinRace(c *realtime.Client, e *control.Engine, lobbySvc *lobby.Service, cat *catalog.Service, env *transport.Envelope) {
payload, _ := env.Payload.(map[string]any)
slot := 0
name := "anon"
@@ -654,8 +654,10 @@ func handleJoinRace(c *realtime.Client, e *control.Engine, lobbySvc *lobby.Servi
driverID = c.ID
}
var deviceID *int
if d, err := lobbySvc.GetDriver(driverID); err == nil {
deviceID = d.DeviceID
if d, err := lobbySvc.GetDriver(driverID); err == nil && d.CarID != nil && *d.CarID != "" {
if carMeta, ok := cat.GetCar(*d.CarID); ok {
deviceID = carMeta.DeviceID
}
}
car, err := e.AddCar(c.ID, name, slot, deviceID)
+16 -9
View File
@@ -11,6 +11,7 @@ import (
"time"
"github.com/pion/webrtc/v4"
"github.com/x0gp/server/internal/catalog"
"github.com/x0gp/server/internal/control"
"github.com/x0gp/server/internal/lobby"
"github.com/x0gp/server/internal/transport"
@@ -31,17 +32,19 @@ type WebRTCService struct {
engine *control.Engine
lobbySvc *lobby.Service
videoSvc *UDPVideoService
catalogSvc *catalog.Service
sessions map[string]*driverSession
sessionsMu sync.RWMutex
}
func NewWebRTCService(logger *slog.Logger, e *control.Engine, lobbySvc *lobby.Service, videoSvc *UDPVideoService) *WebRTCService {
func NewWebRTCService(logger *slog.Logger, e *control.Engine, lobbySvc *lobby.Service, videoSvc *UDPVideoService, catalogSvc *catalog.Service) *WebRTCService {
return &WebRTCService{
logger: logger,
engine: e,
lobbySvc: lobbySvc,
videoSvc: videoSvc,
sessions: make(map[string]*driverSession),
logger: logger,
engine: e,
lobbySvc: lobbySvc,
videoSvc: videoSvc,
catalogSvc: catalogSvc,
sessions: make(map[string]*driverSession),
}
}
@@ -93,10 +96,14 @@ func (s *WebRTCService) ConnectHandler() http.HandlerFunc {
// Resolve device ID for this driver
deviceID := uint8(1) // default fallback
if driver, err := s.lobbySvc.GetDriver(req.DriverID); err == nil && driver.DeviceID != nil {
deviceID = uint8(*driver.DeviceID)
if driver, err := s.lobbySvc.GetDriver(req.DriverID); err == nil && driver.CarID != nil && *driver.CarID != "" {
if car, ok := s.catalogSvc.GetCar(*driver.CarID); ok && car.DeviceID != nil {
deviceID = uint8(*car.DeviceID)
} else {
s.logger.Warn("webrtc client connected but car has no physical device_id assigned in catalog. Defaulting to device 1", "driver_id", req.DriverID, "car_id", *driver.CarID)
}
} else {
s.logger.Warn("webrtc client connected but no physical device_id assigned in lobbySvc. Defaulting to device 1", "driver_id", req.DriverID)
s.logger.Warn("webrtc client connected but no car_id assigned in lobbySvc. Defaulting to device 1", "driver_id", req.DriverID)
}
// Create PeerConnection