feat: order processing

feat: order commands result save/load
This commit is contained in:
Ilia Denisov
2026-02-20 17:44:41 +02:00
committed by GitHub
parent 0c0df976bd
commit 233c9ebc2a
26 changed files with 2028 additions and 385 deletions
+73 -30
View File
@@ -5,6 +5,7 @@ import (
"github.com/google/uuid"
"github.com/iliadenisov/galaxy/internal/model/game"
"github.com/iliadenisov/galaxy/internal/model/order"
"github.com/iliadenisov/galaxy/internal/model/report"
"github.com/iliadenisov/galaxy/internal/repo"
)
@@ -41,9 +42,17 @@ type Repo interface {
// LoadReport loads report for specific turn and player id
LoadReport(uint, uuid.UUID) (*report.Report, error)
// SaveOrder stores order for given turn
SaveOrder(uint, uuid.UUID, *order.Order) error
// LoadOrder loads order for specific turn and player id
LoadOrder(uint, uuid.UUID) (*order.Order, bool, error)
}
type Ctrl interface {
ValidateOrder(actor string, cmd ...order.DecodableCommand) error
// remove below funcs if /command api will be deleted
RaceID(actor string) (uuid.UUID, error)
RaceQuit(actor string) error
RaceVote(actor, acceptor string) error
@@ -94,7 +103,7 @@ func GenerateTurn(configure func(*Param)) (err error) {
if err != nil {
return err
}
err = ec.ExecuteLocked(func(c *Controller) error { return c.MakeTurn() })
err = ec.executeLocked(func(c *Controller) error { return c.MakeTurn() })
return
}
@@ -103,7 +112,15 @@ func ExecuteCommand(configure func(*Param), consumer func(c Ctrl) error) (err er
if err != nil {
return err
}
return ec.ExecuteCommand(func(c *Controller) error { return consumer(c) })
return ec.executeCommand(func(c *Controller) error { return consumer(c) })
}
func ValidateOrder(configure func(*Param), actor string, cmd ...order.DecodableCommand) (err error) {
ec, err := NewRepoController(configure)
if err != nil {
return err
}
return ec.validateOrder(actor, cmd...)
}
func GameState(configure func(*Param)) (s game.State, err error) {
@@ -138,34 +155,6 @@ type RepoController struct {
Repo Repo
}
func (ec *RepoController) ExecuteLocked(consumer func(*Controller) error) (err error) {
if err := ec.Repo.Lock(); err != nil {
return err
}
defer func() {
err = errors.Join(err, ec.Repo.Release())
}()
g, err := ec.Repo.LoadState()
if err != nil {
return err
}
err = consumer(ec.NewGameController(g))
return
}
func (ec *RepoController) ExecuteCommand(consumer func(*Controller) error) (err error) {
return ec.ExecuteLocked(func(c *Controller) error {
err = consumer(c)
if err == nil {
c.Cache.StageCommand()
err = c.saveState()
}
return err
})
}
func NewRepoController(config Configurer) (*RepoController, error) {
c := &Param{
StoragePath: ".",
@@ -189,6 +178,60 @@ func (ec *RepoController) NewGameController(g *game.Game) *Controller {
}
}
func (ec *RepoController) validateOrder(actor string, cmd ...order.DecodableCommand) (err error) {
return ec.executeSafe(func(t uint, c *Controller) error {
id, err := c.RaceID(actor)
if err != nil {
return err
}
err = c.ValidateOrder(actor, cmd...)
if err != nil {
return err
}
o := &order.Order{Commands: make([]order.DecodableCommand, len(cmd))}
copy(o.Commands, cmd)
return ec.Repo.SaveOrder(t, id, o)
})
}
func (ec *RepoController) executeCommand(consumer func(*Controller) error) (err error) {
return ec.executeLocked(func(c *Controller) error {
err = consumer(c)
if err == nil {
c.Cache.StageCommand()
err = c.saveState()
}
return err
})
}
func (ec *RepoController) executeSafe(consumer func(uint, *Controller) error) (err error) {
g, err := ec.Repo.LoadStateSafe()
if err != nil {
return err
}
err = consumer(g.Turn, ec.NewGameController(g))
return
}
func (ec *RepoController) executeLocked(consumer func(*Controller) error) (err error) {
if err := ec.Repo.Lock(); err != nil {
return err
}
defer func() {
err = errors.Join(err, ec.Repo.Release())
}()
g, err := ec.Repo.LoadState()
if err != nil {
return err
}
err = consumer(ec.NewGameController(g))
return
}
func (c *Controller) saveState() error {
return c.Repo.SaveLastState(c.Cache.g)
}