aboutsummaryrefslogtreecommitdiffhomepage
path: root/backend/admin/handler.go
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-02-15 22:13:50 +0900
committernsfisis <nsfisis@gmail.com>2026-02-15 22:16:22 +0900
commit5ed369a6c70707543fd5ec9a13c79851fdfc5d6c (patch)
treee5678d6d88fab3ac0ae8c05b85236f3e7d5eddfd /backend/admin/handler.go
parent87e9f5ed48af3a8dca5f6373ae900336f285eef5 (diff)
downloadphperkaigi-2026-albatross-5ed369a6c70707543fd5ec9a13c79851fdfc5d6c.tar.gz
phperkaigi-2026-albatross-5ed369a6c70707543fd5ec9a13c79851fdfc5d6c.tar.zst
phperkaigi-2026-albatross-5ed369a6c70707543fd5ec9a13c79851fdfc5d6c.zip
refactor(backend): introduce DI interfaces for testability
Replace concrete *db.Queries and *pgxpool.Pool dependencies with db.Querier and db.TxManager interfaces across all handlers, game hub, and auth. This enables unit testing with mocks. - Enable sqlc emit_interface to generate Querier interface - Add TxManager abstraction to encapsulate transactions - Convert auth package-level functions to Authenticator struct - Add TaskQueueInterface/TaskWorkerInterface for game.Hub - Add initial unit tests for game logic and API handlers Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'backend/admin/handler.go')
-rw-r--r--backend/admin/handler.go68
1 files changed, 27 insertions, 41 deletions
diff --git a/backend/admin/handler.go b/backend/admin/handler.go
index e8a7921..6ca0a3f 100644
--- a/backend/admin/handler.go
+++ b/backend/admin/handler.go
@@ -10,7 +10,6 @@ import (
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
- "github.com/jackc/pgx/v5/pgxpool"
"github.com/labstack/echo/v4"
"albatross-2026-backend/account"
@@ -22,13 +21,13 @@ import (
var jst = time.FixedZone("Asia/Tokyo", 9*60*60)
type Handler struct {
- q *db.Queries
- pool *pgxpool.Pool
+ q db.Querier
+ txm db.TxManager
conf *config.Config
}
-func NewHandler(q *db.Queries, pool *pgxpool.Pool, conf *config.Config) *Handler {
- return &Handler{q: q, pool: pool, conf: conf}
+func NewHandler(q db.Querier, txm db.TxManager, conf *config.Config) *Handler {
+ return &Handler{q: q, txm: txm, conf: conf}
}
func (h *Handler) newAdminMiddleware() echo.MiddlewareFunc {
@@ -506,48 +505,35 @@ func (h *Handler) postGameEdit(c echo.Context) error {
}
ctx := c.Request().Context()
- tx, err := h.pool.Begin(ctx)
- if err != nil {
- return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
- }
- defer func() {
- if err := tx.Rollback(ctx); err != nil && err != pgx.ErrTxClosed {
- slog.Error("failed to rollback transaction", "error", err)
+ err = h.txm.RunInTx(ctx, func(qtx db.Querier) error {
+ if err := qtx.UpdateGame(ctx, db.UpdateGameParams{
+ GameID: int32(gameID),
+ GameType: gameType,
+ IsPublic: isPublic,
+ DisplayName: displayName,
+ DurationSeconds: int32(durationSeconds),
+ StartedAt: changedStartedAt,
+ ProblemID: int32(problemID),
+ }); err != nil {
+ return err
}
- }()
-
- qtx := h.q.WithTx(tx)
- err = qtx.UpdateGame(ctx, db.UpdateGameParams{
- GameID: int32(gameID),
- GameType: gameType,
- IsPublic: isPublic,
- DisplayName: displayName,
- DurationSeconds: int32(durationSeconds),
- StartedAt: changedStartedAt,
- ProblemID: int32(problemID),
+ if err := qtx.RemoveAllMainPlayers(ctx, int32(gameID)); err != nil {
+ return err
+ }
+ for _, userID := range mainPlayers {
+ if err := qtx.AddMainPlayer(ctx, db.AddMainPlayerParams{
+ GameID: int32(gameID),
+ UserID: int32(userID),
+ }); err != nil {
+ return err
+ }
+ }
+ return nil
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
}
- err = qtx.RemoveAllMainPlayers(ctx, int32(gameID))
- if err != nil {
- return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
- }
- for _, userID := range mainPlayers {
- err = qtx.AddMainPlayer(ctx, db.AddMainPlayerParams{
- GameID: int32(gameID),
- UserID: int32(userID),
- })
- if err != nil {
- return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
- }
- }
-
- if err := tx.Commit(ctx); err != nil {
- return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
- }
-
return c.Redirect(http.StatusSeeOther, h.conf.BasePath+"admin/games")
}