Alow embedding server
This commit is contained in:
parent
3286105c9c
commit
817f86dcf9
10 changed files with 117 additions and 83 deletions
|
@ -7,6 +7,8 @@ import (
|
|||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"os"
|
||||
|
||||
"code.rocket9labs.com/tslocum/bgammon/pkg/server"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -47,16 +49,12 @@ func main() {
|
|||
}()
|
||||
}
|
||||
|
||||
if debugCommands {
|
||||
allowDebugCommands = debugCommands
|
||||
}
|
||||
|
||||
s := newServer(tz, dataSource)
|
||||
s := server.NewServer(tz, dataSource, debugCommands)
|
||||
if tcpAddress != "" {
|
||||
s.listen("tcp", tcpAddress)
|
||||
s.Listen("tcp", tcpAddress)
|
||||
}
|
||||
if wsAddress != "" {
|
||||
s.listen("ws", wsAddress)
|
||||
s.Listen("ws", wsAddress)
|
||||
}
|
||||
select {}
|
||||
}
|
||||
|
@ -67,8 +65,8 @@ func printRollStatistics() {
|
|||
|
||||
total := 1000000
|
||||
for i := 0; i < total; i++ {
|
||||
roll1 := randInt(6) + 1
|
||||
roll2 := randInt(6) + 1
|
||||
roll1 := server.RandInt(6) + 1
|
||||
roll2 := server.RandInt(6) + 1
|
||||
|
||||
if roll1 == lastroll1 || roll1 == lastroll2 || roll2 == lastroll1 || roll2 == lastroll2 {
|
||||
oneSame++
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package server
|
||||
|
||||
type account struct {
|
||||
id int
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package server
|
||||
|
||||
import (
|
||||
"bytes"
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package server
|
||||
|
||||
import (
|
||||
"bufio"
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package server
|
||||
|
||||
import (
|
||||
"bytes"
|
|
@ -1,4 +1,6 @@
|
|||
package main
|
||||
//go:build database
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -23,16 +25,15 @@ CREATE TABLE game (
|
|||
);
|
||||
`
|
||||
|
||||
func connectDB(dataSource string) (*pgx.Conn, error) {
|
||||
var db *pgx.Conn
|
||||
|
||||
func connectDB(dataSource string) error {
|
||||
var err error
|
||||
db, err := pgx.Connect(context.Background(), dataSource)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return db, nil
|
||||
db, err = pgx.Connect(context.Background(), dataSource)
|
||||
return err
|
||||
}
|
||||
|
||||
func begin(db *pgx.Conn) (pgx.Tx, error) {
|
||||
func begin() (pgx.Tx, error) {
|
||||
tx, err := db.Begin(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -45,12 +46,12 @@ func begin(db *pgx.Conn) (pgx.Tx, error) {
|
|||
return tx, nil
|
||||
}
|
||||
|
||||
func testDBConnection(db *pgx.Conn) error {
|
||||
func testDBConnection() error {
|
||||
_, err := db.Exec(context.Background(), "SELECT 1=1")
|
||||
return err
|
||||
}
|
||||
|
||||
func initDB(db *pgx.Conn) {
|
||||
func initDB() {
|
||||
tx, err := begin(db)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to initialize database: %s", err)
|
||||
|
@ -72,8 +73,8 @@ func initDB(db *pgx.Conn) {
|
|||
log.Println("Initialized database schema")
|
||||
}
|
||||
|
||||
func recordGameResult(conn *pgx.Conn, g *bgammon.Game, winType int) error {
|
||||
if g.Started.IsZero() || g.Ended.IsZero() || g.Winner == 0 {
|
||||
func recordGameResult(g *bgammon.Game, winType int) error {
|
||||
if db == nil || g.Started.IsZero() || g.Ended.IsZero() || g.Winner == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -91,16 +92,7 @@ func recordGameResult(conn *pgx.Conn, g *bgammon.Game, winType int) error {
|
|||
return err
|
||||
}
|
||||
|
||||
type serverStatsEntry struct {
|
||||
Date string
|
||||
Games int
|
||||
}
|
||||
|
||||
type serverStatsResult struct {
|
||||
History []*serverStatsEntry
|
||||
}
|
||||
|
||||
func serverStats(conn *pgx.Conn, tz *time.Location) (*serverStatsResult, error) {
|
||||
func serverStats(tz *time.Location) (*serverStatsResult, error) {
|
||||
tx, err := begin(conn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -155,18 +147,7 @@ func serverStats(conn *pgx.Conn, tz *time.Location) (*serverStatsResult, error)
|
|||
return result, nil
|
||||
}
|
||||
|
||||
type wildBGStatsEntry struct {
|
||||
Date string
|
||||
Percent float64
|
||||
Wins int
|
||||
Losses int
|
||||
}
|
||||
|
||||
type wildBGStatsResult struct {
|
||||
History []*wildBGStatsEntry
|
||||
}
|
||||
|
||||
func wildBGStats(conn *pgx.Conn, tz *time.Location) (*wildBGStatsResult, error) {
|
||||
func wildBGStats(tz *time.Location) (*wildBGStatsResult, error) {
|
||||
tx, err := begin(conn)
|
||||
if err != nil {
|
||||
return nil, err
|
21
pkg/server/database_common.go
Normal file
21
pkg/server/database_common.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package server
|
||||
|
||||
type serverStatsEntry struct {
|
||||
Date string
|
||||
Games int
|
||||
}
|
||||
|
||||
type serverStatsResult struct {
|
||||
History []*serverStatsEntry
|
||||
}
|
||||
|
||||
type wildBGStatsEntry struct {
|
||||
Date string
|
||||
Percent float64
|
||||
Wins int
|
||||
Losses int
|
||||
}
|
||||
|
||||
type wildBGStatsResult struct {
|
||||
History []*wildBGStatsEntry
|
||||
}
|
32
pkg/server/database_disabled.go
Normal file
32
pkg/server/database_disabled.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
//go:build !database
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"code.rocket9labs.com/tslocum/bgammon"
|
||||
)
|
||||
|
||||
func connectDB(dataSource string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func testDBConnection() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func initDB() {
|
||||
}
|
||||
|
||||
func recordGameResult(g *bgammon.Game, winType int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func serverStats(tz *time.Location) (*serverStatsResult, error) {
|
||||
return &serverStatsResult{}, nil
|
||||
}
|
||||
|
||||
func wildBGStats(tz *time.Location) (*wildBGStatsResult, error) {
|
||||
return &wildBGStatsResult{}, nil
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package server
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
@ -45,12 +45,12 @@ func (g *serverGame) roll(player int) bool {
|
|||
if g.Roll1 != 0 {
|
||||
return false
|
||||
}
|
||||
g.Roll1 = randInt(6) + 1
|
||||
g.Roll1 = RandInt(6) + 1
|
||||
} else {
|
||||
if g.Roll2 != 0 {
|
||||
return false
|
||||
}
|
||||
g.Roll2 = randInt(6) + 1
|
||||
g.Roll2 = RandInt(6) + 1
|
||||
}
|
||||
|
||||
if g.Started.IsZero() {
|
||||
|
@ -66,8 +66,8 @@ func (g *serverGame) roll(player int) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
g.Roll1 = randInt(6) + 1
|
||||
g.Roll2 = randInt(6) + 1
|
||||
g.Roll1 = RandInt(6) + 1
|
||||
g.Roll2 = RandInt(6) + 1
|
||||
|
||||
return true
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ func (g *serverGame) addClient(client *serverClient) (spectator bool) {
|
|||
client.playerNumber = 1
|
||||
playerNumber = 1
|
||||
default:
|
||||
if randInt(2) == 0 {
|
||||
if RandInt(2) == 0 {
|
||||
g.client1 = client
|
||||
g.Player1.Name = string(client.name)
|
||||
client.playerNumber = 1
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package server
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -16,7 +16,6 @@ import (
|
|||
"time"
|
||||
|
||||
"code.rocket9labs.com/tslocum/bgammon"
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
const clientTimeout = 40 * time.Second
|
||||
|
@ -50,11 +49,9 @@ type server struct {
|
|||
gamesCacheLock sync.Mutex
|
||||
|
||||
tz *time.Location
|
||||
|
||||
db *pgx.Conn
|
||||
}
|
||||
|
||||
func newServer(tz string, dataSource string) *server {
|
||||
func NewServer(tz string, dataSource string, allowDebug bool) *server {
|
||||
const bufferSize = 10
|
||||
s := &server{
|
||||
newGameIDs: make(chan int),
|
||||
|
@ -74,22 +71,23 @@ func newServer(tz string, dataSource string) *server {
|
|||
}
|
||||
|
||||
if dataSource != "" {
|
||||
var err error
|
||||
s.db, err = connectDB(dataSource)
|
||||
err := connectDB(dataSource)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to connect to database: %s", err)
|
||||
}
|
||||
|
||||
err = testDBConnection(s.db)
|
||||
err = testDBConnection()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to test database connection: %s", err)
|
||||
}
|
||||
|
||||
initDB(s.db)
|
||||
initDB()
|
||||
|
||||
log.Println("Connected to database successfully")
|
||||
}
|
||||
|
||||
allowDebugCommands = allowDebug
|
||||
|
||||
go s.handleNewGameIDs()
|
||||
go s.handleNewClientIDs()
|
||||
go s.handleCommands()
|
||||
|
@ -136,12 +134,9 @@ func (s *server) handleListMatches(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func (s *server) handlePrintStats(w http.ResponseWriter, r *http.Request) {
|
||||
if s.db == nil {
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
stats, err := serverStats(s.db, s.tz)
|
||||
stats, err := serverStats(s.tz)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to fetch server statistics: %s", err)
|
||||
}
|
||||
|
@ -153,12 +148,9 @@ func (s *server) handlePrintStats(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func (s *server) handlePrintWildBGStats(w http.ResponseWriter, r *http.Request) {
|
||||
if s.db == nil {
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
stats, err := wildBGStats(s.db, s.tz)
|
||||
stats, err := wildBGStats(s.tz)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to fetch wildbg statistics: %s", err)
|
||||
}
|
||||
|
@ -205,7 +197,21 @@ func (s *server) listenWebSocket(address string) {
|
|||
log.Fatalf("failed to listen on %s: %s", address, err)
|
||||
}
|
||||
|
||||
func (s *server) listen(network string, address string) {
|
||||
func (s *server) handleLocal(conns chan net.Conn) {
|
||||
for {
|
||||
local, remote := net.Pipe()
|
||||
conns <- local
|
||||
go s.handleConnection(remote)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *server) ListenLocal() chan net.Conn {
|
||||
conns := make(chan net.Conn)
|
||||
go s.handleLocal(conns)
|
||||
return conns
|
||||
}
|
||||
|
||||
func (s *server) Listen(network string, address string) {
|
||||
if strings.ToLower(network) == "ws" {
|
||||
go s.listenWebSocket(address)
|
||||
return
|
||||
|
@ -380,7 +386,7 @@ func (s *server) handleNewClientIDs() {
|
|||
// randomUsername returns a random guest username, and assumes clients are already locked.
|
||||
func (s *server) randomUsername() []byte {
|
||||
for {
|
||||
name := []byte(fmt.Sprintf("Guest%d", 100+randInt(900)))
|
||||
name := []byte(fmt.Sprintf("Guest%d", 100+RandInt(900)))
|
||||
|
||||
if s.clientByUsername(name) == nil {
|
||||
return name
|
||||
|
@ -864,11 +870,9 @@ COMMANDS:
|
|||
winEvent.Player = clientGame.Player2.Name
|
||||
}
|
||||
|
||||
if s.db != nil {
|
||||
err := recordGameResult(s.db, clientGame.Game, 4)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to record game result: %s", err)
|
||||
}
|
||||
err := recordGameResult(clientGame.Game, 4)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to record game result: %s", err)
|
||||
}
|
||||
}
|
||||
clientGame.eachClient(func(client *serverClient) {
|
||||
|
@ -1094,11 +1098,9 @@ COMMANDS:
|
|||
}
|
||||
}
|
||||
|
||||
if s.db != nil {
|
||||
err := recordGameResult(s.db, clientGame.Game, winPoints)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to record game result: %s", err)
|
||||
}
|
||||
err := recordGameResult(clientGame.Game, winPoints)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to record game result: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1357,7 +1359,7 @@ COMMANDS:
|
|||
}
|
||||
}
|
||||
|
||||
func randInt(max int) int {
|
||||
func RandInt(max int) int {
|
||||
i, err := rand.Int(rand.Reader, big.NewInt(int64(max)))
|
||||
if err != nil {
|
||||
panic(err)
|
Loading…
Reference in a new issue