add db package
db package allows for writing games to postgres db
This commit is contained in:
parent
7426ddaf74
commit
38368ba151
2 changed files with 106 additions and 0 deletions
97
db/db.go
Normal file
97
db/db.go
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/BattlesnakeOfficial/rules/board"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
// the db package provides a simple interface to interact with a PostgreSQL database, it is extremely simple and only writing, reading and deleting game info
|
||||
|
||||
// @ author Bhavnoor Singh Saroya
|
||||
|
||||
// Database wraps pgxpool
|
||||
type Database struct {
|
||||
Pool *pgxpool.Pool
|
||||
}
|
||||
|
||||
// Connect initializes the pool and creates the table if needed
|
||||
func Connect(dsn string) (*Database, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
pool, err := pgxpool.New(ctx, dsn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("db connect: %w", err)
|
||||
}
|
||||
|
||||
// Ensure table exists
|
||||
_, err = pool.Exec(ctx, `
|
||||
CREATE TABLE IF NOT EXISTS items (
|
||||
id UUID PRIMARY KEY,
|
||||
info JSONB NOT NULL,
|
||||
frames JSONB[]
|
||||
)
|
||||
`)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create table: %w", err)
|
||||
}
|
||||
|
||||
return &Database{Pool: pool}, nil
|
||||
}
|
||||
|
||||
func (db *Database) GetInfo(ctx context.Context, id string) (*board.Game, error) {
|
||||
var gameData []byte
|
||||
var it board.Game
|
||||
err := db.Pool.QueryRow(ctx,
|
||||
"SELECT info FROM items WHERE id=$1", id).
|
||||
Scan(&gameData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 2. Unmarshal the byte slice into the struct.
|
||||
err = json.Unmarshal(gameData, &it)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &it, nil
|
||||
}
|
||||
|
||||
func (db *Database) WriteInfo(ctx context.Context, info board.Game, frames []board.GameEvent) error {
|
||||
var err error
|
||||
var uuid string = info.ID
|
||||
// 1. Marshal the struct into a byte slice.
|
||||
gameData, err := json.Marshal(info)
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshal game info: %w", err)
|
||||
}
|
||||
|
||||
// convert []board.GameEvent to []json.RawMessage
|
||||
var framesData []json.RawMessage
|
||||
for _, f := range frames {
|
||||
b, err := json.Marshal(f)
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshal frame: %w", err)
|
||||
}
|
||||
framesData = append(framesData, b)
|
||||
}
|
||||
|
||||
// use pgtype to wrap into postgres []JSONB
|
||||
_, errr := db.Pool.Exec(ctx,
|
||||
"INSERT INTO items (id, info, frames) VALUES ($1, $2, $3)",
|
||||
uuid, gameData, framesData)
|
||||
if errr != nil {
|
||||
print("error writing to db, bad stuff happened: ")
|
||||
// panic(fmt.Sprintf("Error inserting item: %v", err))
|
||||
return fmt.Errorf("insert item: %w", errr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *Database) Delete(ctx context.Context, id int) error {
|
||||
_, err := db.Pool.Exec(ctx,
|
||||
"DELETE FROM items WHERE id=$1", id)
|
||||
return err
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue