feat(grpc): Add initial server implementation

This commit is contained in:
Jemma Poffinbarger
2026-04-10 18:29:14 -05:00
parent b9d3bd3482
commit a94b81d951
10 changed files with 262 additions and 3 deletions

View File

@@ -0,0 +1,62 @@
package database
import (
"database/sql"
"time"
pb "github.com/PretendoNetwork/grpc/go/nex/matchmaking/v1"
"github.com/PretendoNetwork/splatoon/globals"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func GetOpenActiveMatches() (*[]pb.ActiveMatch, error) {
rows, err := globals.Postgres.Query(`
SELECT g.id, g.started_time, g.participants,g.owner_pid,s.game_mode,g.flags
FROM matchmaking.gatherings g
JOIN matchmaking.matchmake_sessions s ON (g.id = s.id)
WHERE array_length(g.participants, 1) > 4 AND s.open_participation = true
LIMIT 25`)
if err != nil {
if err == sql.ErrNoRows {
globals.Logger.Error("Error no matches found")
return nil, status.Errorf(codes.Internal, "internal server error")
} else {
globals.Logger.Error("Error unknown fetching matches")
return nil, status.Errorf(codes.Internal, "internal server error")
}
}
defer rows.Close()
var matches []pb.ActiveMatch
for rows.Next() {
var id uint64
var startTime time.Time
var participants Participants
var ownerPID uint32
var gameMode uint64
var flags uint64
err := rows.Scan(&id, &startTime, &participants, &ownerPID, &gameMode, &flags)
if err != nil {
globals.Logger.Error("Error parsing row contents")
globals.Logger.Error(err.Error())
return nil, status.Errorf(codes.Internal, "internal server error")
}
matches = append(matches, pb.ActiveMatch{
Id: uint32(id),
StartTime: uint64(startTime.Unix()),
Participants: participants,
OwnerPid: ownerPID,
HostPid: ownerPID,
GameMode: gameMode,
Flags: flags,
})
}
return &matches, nil
}

72
database/participants.go Normal file
View File

@@ -0,0 +1,72 @@
package database
import (
"database/sql/driver"
"encoding/csv"
"fmt"
"strconv"
"strings"
)
type Participants []uint32
func (p Participants) Value() (driver.Value, error) {
return p, nil
}
func (l *Participants) Scan(value any) error {
if value == nil {
return nil
}
// * Ensure the value is in the right format
var pgArray string
switch v := value.(type) {
case []byte:
pgArray = string(v)
case string:
pgArray = v
default:
return fmt.Errorf("unsupported Scan type for List: %T", value)
}
// * Postgres formats arrays in curly braces,
// * such as `{"string1"}`
if len(pgArray) < 2 || pgArray[0] != '{' || pgArray[len(pgArray)-1] != '}' {
return fmt.Errorf("invalid PostgreSQL array format: %s", pgArray)
}
pgArray = strings.TrimSuffix(pgArray, "}")
pgArray = strings.TrimPrefix(pgArray, "{")
// * Bail if array is empty, who cares
if pgArray == "" {
return nil
}
var elements []string
var err error
reader := csv.NewReader(strings.NewReader(pgArray))
reader.Comma = ','
elements, err = reader.Read()
if err != nil {
return nil
}
result := make(Participants, 0, len(elements))
for _, element := range elements {
i, err := strconv.ParseUint(element, 10, 32)
if err != nil {
return err
}
result = append(result, uint32(i))
}
*l = result
return nil
}