refactor: remove persister abstraction layer
Inline persistence logic directly into game stores and handlers: - game/persist.go: DB mapping methods on GameStore and GameInstance - snake/persist.go: DB mapping methods on SnakeStore and SnakeGameInstance - Chat persistence inlined into c4game handlers - Delete db/persister.go (GamePersister, SnakePersister, ChatPersister) - Stores now take *repository.Queries directly instead of Persister interface
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
package c4game
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -10,14 +12,14 @@ import (
|
||||
"github.com/alexedwards/scs/v2"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/ryanhamamura/c4/db"
|
||||
"github.com/ryanhamamura/c4/db/repository"
|
||||
"github.com/ryanhamamura/c4/features/c4game/components"
|
||||
"github.com/ryanhamamura/c4/features/c4game/pages"
|
||||
"github.com/ryanhamamura/c4/game"
|
||||
"github.com/starfederation/datastar-go/datastar"
|
||||
)
|
||||
|
||||
func HandleGamePage(store *game.GameStore, sessions *scs.SessionManager, chatPersister *db.ChatPersister) http.HandlerFunc {
|
||||
func HandleGamePage(store *game.GameStore, sessions *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
gameID := chi.URLParam(r, "game_id")
|
||||
|
||||
@@ -73,8 +75,8 @@ func HandleGamePage(store *game.GameStore, sessions *scs.SessionManager, chatPer
|
||||
|
||||
// Player is in the game — render full game page
|
||||
g := gi.GetGame()
|
||||
uiMsgs, _ := chatPersister.LoadChatMessages(gameID)
|
||||
msgs := uiChatToComponents(uiMsgs)
|
||||
chatMsgs := loadChatMessages(queries, gameID)
|
||||
msgs := chatToComponents(chatMsgs)
|
||||
|
||||
if err := pages.GamePage(g, myColor, msgs).Render(r.Context(), w); err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
@@ -82,7 +84,7 @@ func HandleGamePage(store *game.GameStore, sessions *scs.SessionManager, chatPer
|
||||
}
|
||||
}
|
||||
|
||||
func HandleGameEvents(store *game.GameStore, nc *nats.Conn, sessions *scs.SessionManager, chatPersister *db.ChatPersister) http.HandlerFunc {
|
||||
func HandleGameEvents(store *game.GameStore, nc *nats.Conn, sessions *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
gameID := chi.URLParam(r, "game_id")
|
||||
|
||||
@@ -103,9 +105,9 @@ func HandleGameEvents(store *game.GameStore, nc *nats.Conn, sessions *scs.Sessio
|
||||
sse := datastar.NewSSE(w, r)
|
||||
|
||||
// Load initial chat messages
|
||||
uiMsgs, _ := chatPersister.LoadChatMessages(gameID)
|
||||
chatMsgs := loadChatMessages(queries, gameID)
|
||||
var chatMu sync.Mutex
|
||||
chatMessages := uiChatToComponents(uiMsgs)
|
||||
chatMessages := chatToComponents(chatMsgs)
|
||||
|
||||
// Send initial render of all components
|
||||
sendGameComponents(sse, gi, myColor, chatMessages, &chatMu, gameID)
|
||||
@@ -203,7 +205,7 @@ func HandleDropPiece(store *game.GameStore, sessions *scs.SessionManager) http.H
|
||||
}
|
||||
}
|
||||
|
||||
func HandleSendChat(store *game.GameStore, nc *nats.Conn, sessions *scs.SessionManager, chatPersister *db.ChatPersister) http.HandlerFunc {
|
||||
func HandleSendChat(store *game.GameStore, nc *nats.Conn, sessions *scs.SessionManager, queries *repository.Queries) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
gameID := chi.URLParam(r, "game_id")
|
||||
|
||||
@@ -254,7 +256,7 @@ func HandleSendChat(store *game.GameStore, nc *nats.Conn, sessions *scs.SessionM
|
||||
Message: signals.ChatMsg,
|
||||
Time: time.Now().UnixMilli(),
|
||||
}
|
||||
chatPersister.SaveChatMessage(gameID, cm)
|
||||
saveChatMessage(queries, gameID, cm)
|
||||
|
||||
data, err := json.Marshal(cm)
|
||||
if err != nil {
|
||||
@@ -353,10 +355,40 @@ func sendGameComponents(sse *datastar.ServerSentEventGenerator, gi *game.GameIns
|
||||
sse.PatchElementTempl(components.Chat(msgs, gameID), datastar.WithSelectorID("c4-chat")) //nolint:errcheck
|
||||
}
|
||||
|
||||
// uiChatToComponents converts ui.C4ChatMessage slice to components.ChatMessage slice.
|
||||
func uiChatToComponents(uiMsgs []game.ChatMessage) []components.ChatMessage {
|
||||
msgs := make([]components.ChatMessage, len(uiMsgs))
|
||||
for i, m := range uiMsgs {
|
||||
// Chat persistence helpers — inlined from the former ChatPersister.
|
||||
|
||||
func saveChatMessage(queries *repository.Queries, gameID string, msg game.ChatMessage) {
|
||||
queries.CreateChatMessage(context.Background(), repository.CreateChatMessageParams{ //nolint:errcheck
|
||||
GameID: gameID,
|
||||
Nickname: msg.Nickname,
|
||||
Color: int64(msg.Color),
|
||||
Message: msg.Message,
|
||||
CreatedAt: msg.Time,
|
||||
})
|
||||
}
|
||||
|
||||
func loadChatMessages(queries *repository.Queries, gameID string) []game.ChatMessage {
|
||||
rows, err := queries.GetChatMessages(context.Background(), gameID)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
msgs := make([]game.ChatMessage, len(rows))
|
||||
for i, r := range rows {
|
||||
msgs[i] = game.ChatMessage{
|
||||
Nickname: r.Nickname,
|
||||
Color: int(r.Color),
|
||||
Message: r.Message,
|
||||
Time: r.CreatedAt,
|
||||
}
|
||||
}
|
||||
// DB returns newest-first; reverse for display
|
||||
slices.Reverse(msgs)
|
||||
return msgs
|
||||
}
|
||||
|
||||
func chatToComponents(chatMsgs []game.ChatMessage) []components.ChatMessage {
|
||||
msgs := make([]components.ChatMessage, len(chatMsgs))
|
||||
for i, m := range chatMsgs {
|
||||
msgs[i] = components.ChatMessage{
|
||||
Nickname: m.Nickname,
|
||||
Color: m.Color,
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"github.com/alexedwards/scs/v2"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/ryanhamamura/c4/db"
|
||||
"github.com/ryanhamamura/c4/db/repository"
|
||||
"github.com/ryanhamamura/c4/game"
|
||||
)
|
||||
|
||||
@@ -13,14 +13,14 @@ func SetupRoutes(
|
||||
store *game.GameStore,
|
||||
nc *nats.Conn,
|
||||
sessions *scs.SessionManager,
|
||||
chatPersister *db.ChatPersister,
|
||||
queries *repository.Queries,
|
||||
) error {
|
||||
router.Get("/game/{game_id}", HandleGamePage(store, sessions, chatPersister))
|
||||
router.Get("/game/{game_id}/events", HandleGameEvents(store, nc, sessions, chatPersister))
|
||||
router.Get("/game/{game_id}", HandleGamePage(store, sessions, queries))
|
||||
router.Get("/game/{game_id}/events", HandleGameEvents(store, nc, sessions, queries))
|
||||
|
||||
router.Route("/api/game/{game_id}", func(r chi.Router) {
|
||||
r.Post("/drop", HandleDropPiece(store, sessions))
|
||||
r.Post("/chat", HandleSendChat(store, nc, sessions, chatPersister))
|
||||
r.Post("/chat", HandleSendChat(store, nc, sessions, queries))
|
||||
r.Post("/join", HandleSetNickname(store, sessions))
|
||||
r.Post("/rematch", HandleRematch(store, sessions))
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user