Add backend foundation and config-driven workbench
This commit is contained in:
263
backend/internal/store/postgres/event_store.go
Normal file
263
backend/internal/store/postgres/event_store.go
Normal file
@@ -0,0 +1,263 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
type Event struct {
|
||||
ID string
|
||||
PublicID string
|
||||
Slug string
|
||||
DisplayName string
|
||||
Summary *string
|
||||
Status string
|
||||
CurrentReleaseID *string
|
||||
CurrentReleasePubID *string
|
||||
ConfigLabel *string
|
||||
ManifestURL *string
|
||||
ManifestChecksum *string
|
||||
RouteCode *string
|
||||
}
|
||||
|
||||
type EventRelease struct {
|
||||
ID string
|
||||
PublicID string
|
||||
EventID string
|
||||
ReleaseNo int
|
||||
ConfigLabel string
|
||||
ManifestURL string
|
||||
ManifestChecksum *string
|
||||
RouteCode *string
|
||||
BuildID *string
|
||||
Status string
|
||||
PublishedAt time.Time
|
||||
}
|
||||
|
||||
type CreateGameSessionParams struct {
|
||||
SessionPublicID string
|
||||
UserID string
|
||||
EventID string
|
||||
EventReleaseID string
|
||||
DeviceKey string
|
||||
ClientType string
|
||||
RouteCode *string
|
||||
SessionTokenHash string
|
||||
SessionTokenExpiresAt time.Time
|
||||
}
|
||||
|
||||
type GameSession struct {
|
||||
ID string
|
||||
SessionPublicID string
|
||||
UserID string
|
||||
EventID string
|
||||
EventReleaseID string
|
||||
DeviceKey string
|
||||
ClientType string
|
||||
RouteCode *string
|
||||
Status string
|
||||
SessionTokenExpiresAt time.Time
|
||||
}
|
||||
|
||||
func (s *Store) GetEventByPublicID(ctx context.Context, eventPublicID string) (*Event, error) {
|
||||
row := s.pool.QueryRow(ctx, `
|
||||
SELECT
|
||||
e.id,
|
||||
e.event_public_id,
|
||||
e.slug,
|
||||
e.display_name,
|
||||
e.summary,
|
||||
e.status,
|
||||
e.current_release_id,
|
||||
er.release_public_id,
|
||||
er.config_label,
|
||||
er.manifest_url,
|
||||
er.manifest_checksum_sha256,
|
||||
er.route_code
|
||||
FROM events e
|
||||
LEFT JOIN event_releases er ON er.id = e.current_release_id
|
||||
WHERE e.event_public_id = $1
|
||||
LIMIT 1
|
||||
`, eventPublicID)
|
||||
|
||||
var event Event
|
||||
err := row.Scan(
|
||||
&event.ID,
|
||||
&event.PublicID,
|
||||
&event.Slug,
|
||||
&event.DisplayName,
|
||||
&event.Summary,
|
||||
&event.Status,
|
||||
&event.CurrentReleaseID,
|
||||
&event.CurrentReleasePubID,
|
||||
&event.ConfigLabel,
|
||||
&event.ManifestURL,
|
||||
&event.ManifestChecksum,
|
||||
&event.RouteCode,
|
||||
)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get event by public id: %w", err)
|
||||
}
|
||||
return &event, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetEventByID(ctx context.Context, eventID string) (*Event, error) {
|
||||
row := s.pool.QueryRow(ctx, `
|
||||
SELECT
|
||||
e.id,
|
||||
e.event_public_id,
|
||||
e.slug,
|
||||
e.display_name,
|
||||
e.summary,
|
||||
e.status,
|
||||
e.current_release_id,
|
||||
er.release_public_id,
|
||||
er.config_label,
|
||||
er.manifest_url,
|
||||
er.manifest_checksum_sha256,
|
||||
er.route_code
|
||||
FROM events e
|
||||
LEFT JOIN event_releases er ON er.id = e.current_release_id
|
||||
WHERE e.id = $1
|
||||
LIMIT 1
|
||||
`, eventID)
|
||||
|
||||
var event Event
|
||||
err := row.Scan(
|
||||
&event.ID,
|
||||
&event.PublicID,
|
||||
&event.Slug,
|
||||
&event.DisplayName,
|
||||
&event.Summary,
|
||||
&event.Status,
|
||||
&event.CurrentReleaseID,
|
||||
&event.CurrentReleasePubID,
|
||||
&event.ConfigLabel,
|
||||
&event.ManifestURL,
|
||||
&event.ManifestChecksum,
|
||||
&event.RouteCode,
|
||||
)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get event by id: %w", err)
|
||||
}
|
||||
return &event, nil
|
||||
}
|
||||
|
||||
func (s *Store) NextEventReleaseNo(ctx context.Context, eventID string) (int, error) {
|
||||
var next int
|
||||
if err := s.pool.QueryRow(ctx, `
|
||||
SELECT COALESCE(MAX(release_no), 0) + 1
|
||||
FROM event_releases
|
||||
WHERE event_id = $1
|
||||
`, eventID).Scan(&next); err != nil {
|
||||
return 0, fmt.Errorf("next event release no: %w", err)
|
||||
}
|
||||
return next, nil
|
||||
}
|
||||
|
||||
type CreateEventReleaseParams struct {
|
||||
PublicID string
|
||||
EventID string
|
||||
ReleaseNo int
|
||||
ConfigLabel string
|
||||
ManifestURL string
|
||||
ManifestChecksum *string
|
||||
RouteCode *string
|
||||
BuildID *string
|
||||
Status string
|
||||
PayloadJSON string
|
||||
}
|
||||
|
||||
func (s *Store) CreateEventRelease(ctx context.Context, tx Tx, params CreateEventReleaseParams) (*EventRelease, error) {
|
||||
row := tx.QueryRow(ctx, `
|
||||
INSERT INTO event_releases (
|
||||
release_public_id,
|
||||
event_id,
|
||||
release_no,
|
||||
config_label,
|
||||
manifest_url,
|
||||
manifest_checksum_sha256,
|
||||
route_code,
|
||||
build_id,
|
||||
status,
|
||||
payload_jsonb
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10::jsonb)
|
||||
RETURNING id, release_public_id, event_id, release_no, config_label, manifest_url, manifest_checksum_sha256, route_code, build_id, status, published_at
|
||||
`, params.PublicID, params.EventID, params.ReleaseNo, params.ConfigLabel, params.ManifestURL, params.ManifestChecksum, params.RouteCode, params.BuildID, params.Status, params.PayloadJSON)
|
||||
|
||||
var item EventRelease
|
||||
if err := row.Scan(
|
||||
&item.ID,
|
||||
&item.PublicID,
|
||||
&item.EventID,
|
||||
&item.ReleaseNo,
|
||||
&item.ConfigLabel,
|
||||
&item.ManifestURL,
|
||||
&item.ManifestChecksum,
|
||||
&item.RouteCode,
|
||||
&item.BuildID,
|
||||
&item.Status,
|
||||
&item.PublishedAt,
|
||||
); err != nil {
|
||||
return nil, fmt.Errorf("create event release: %w", err)
|
||||
}
|
||||
return &item, nil
|
||||
}
|
||||
|
||||
func (s *Store) SetCurrentEventRelease(ctx context.Context, tx Tx, eventID, releaseID string) error {
|
||||
if _, err := tx.Exec(ctx, `
|
||||
UPDATE events
|
||||
SET current_release_id = $2
|
||||
WHERE id = $1
|
||||
`, eventID, releaseID); err != nil {
|
||||
return fmt.Errorf("set current event release: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) CreateGameSession(ctx context.Context, tx Tx, params CreateGameSessionParams) (*GameSession, error) {
|
||||
row := tx.QueryRow(ctx, `
|
||||
INSERT INTO game_sessions (
|
||||
session_public_id,
|
||||
user_id,
|
||||
event_id,
|
||||
event_release_id,
|
||||
device_key,
|
||||
client_type,
|
||||
route_code,
|
||||
session_token_hash,
|
||||
session_token_expires_at
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||
RETURNING id, session_public_id, user_id, event_id, event_release_id, device_key, client_type, route_code, status, session_token_expires_at
|
||||
`, params.SessionPublicID, params.UserID, params.EventID, params.EventReleaseID, params.DeviceKey, params.ClientType, params.RouteCode, params.SessionTokenHash, params.SessionTokenExpiresAt)
|
||||
|
||||
var session GameSession
|
||||
err := row.Scan(
|
||||
&session.ID,
|
||||
&session.SessionPublicID,
|
||||
&session.UserID,
|
||||
&session.EventID,
|
||||
&session.EventReleaseID,
|
||||
&session.DeviceKey,
|
||||
&session.ClientType,
|
||||
&session.RouteCode,
|
||||
&session.Status,
|
||||
&session.SessionTokenExpiresAt,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create game session: %w", err)
|
||||
}
|
||||
return &session, nil
|
||||
}
|
||||
Reference in New Issue
Block a user