refactor: executors and routers

* refactor: executors and routers
This commit is contained in:
Ilia Denisov
2026-02-09 15:53:34 +03:00
committed by GitHub
parent e48a0c8b96
commit d9c8de27e5
38 changed files with 508 additions and 838 deletions
+49 -27
View File
@@ -1,47 +1,69 @@
package handler
import (
"errors"
"encoding/json"
"fmt"
"net/http"
"github.com/iliadenisov/galaxy/internal/controller"
"github.com/iliadenisov/galaxy/internal/game"
"github.com/gin-gonic/gin"
"github.com/iliadenisov/galaxy/internal/model/rest"
)
type CommandExecutor func(controller.Configurer, rest.Command) error
var (
ErrCommandNotProcessed = errors.New("command was not processed by executor")
)
func CommandHandler(c *gin.Context, configurer controller.Configurer, executor CommandExecutor) {
func CommandHandler(c *gin.Context, executor CommandExecutor) {
var cmd rest.Command
if err := c.ShouldBindJSON(&cmd); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
if errorResponded(c, c.ShouldBindJSON(&cmd)) {
return
}
err := executor(configurer, cmd)
switch {
case err == nil:
c.Status(http.StatusOK)
case errors.Is(err, ErrCommandNotProcessed):
c.Status(http.StatusInternalServerError) // TODO: add error text?
commands := make([]Command, 0)
for i := range cmd.Commands {
command, err := parseCommand(cmd.Actor, cmd.Commands[i])
if errorResponded(c, err) {
return
}
commands = append(commands, command)
}
if len(commands) == 0 {
c.JSON(http.StatusBadRequest, gin.H{"error": "no commands given"})
return
}
if errorResponded(c, executor.Execute(commands...)) {
return
}
c.Status(http.StatusNoContent)
}
func parseCommand(actor string, c json.RawMessage) (Command, error) {
meta := new(rest.CommandMeta)
if err := json.Unmarshal(c, meta); err != nil {
return nil, err
}
switch t := meta.Type; t {
case rest.CommandTypeVote:
return giveVotes(actor, c)
case rest.CommandTypeRelation:
return updateRelation(actor, c)
default:
// TODO: separate invalid input and game state errors
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return nil, fmt.Errorf("unknown comman type: %s", t)
}
}
func ExecuteCommand(config controller.Configurer, cmd rest.Command) error {
switch {
case cmd.DeclareWar != nil:
return game.DeclareWar(config, cmd.Race, cmd.DeclareWar.Opponent)
case cmd.DeclarePeace != nil:
return game.DeclarePeace(config, cmd.Race, cmd.DeclareWar.Opponent)
default:
return ErrCommandNotProcessed
func giveVotes(actor string, c json.RawMessage) (Command, error) {
var v rest.CommandVote
if err := json.Unmarshal(c, &v); err != nil {
return nil, err
}
return func(c controller.Ctrl) error { return c.GiveVotes(actor, v.Recipient) }, nil
}
func updateRelation(actor string, c json.RawMessage) (Command, error) {
var v rest.CommandUpdateRelation
if err := json.Unmarshal(c, &v); err != nil {
return nil, err
}
return func(c controller.Ctrl) error { return c.UpdateRelation(actor, v.Opponent, v.Relation) }, nil
}