package api import ( "context" "database/sql" "time" "github.com/cosmic-clash/cosmic-clash/server/domain" "github.com/cosmic-clash/cosmic-clash/server/store" ) // AssignmentProviderFromStore adapts the durable player-scoped assignment // projection to the HTTP boundary. The store query filters expiry and binds // both match and player; the API still performs its response-shape checks. func AssignmentProviderFromStore(db *sql.DB) AssignmentProvider { return func(ctx context.Context, playerID, matchID string, now time.Time) (AssignmentView, error) { assignment, err := store.GetAssignment(ctx, db, playerID, matchID, now) if err != nil { return AssignmentView{}, err } return AssignmentView{ MatchID: assignment.MatchID, ServerID: assignment.ServerID, PlayerID: assignment.PlayerID, Slot: assignment.Slot, ExpiresAt: assignment.ExpiresAt, ProtocolVersion: assignment.ProtocolVersion, Transport: assignment.Transport, JoinAuthorisation: assignment.JoinAuthorisation, Endpoint: assignment.Endpoint, Revision: assignment.Revision, }, nil } } type postgresProposalBackend struct{ db *sql.DB } func (p postgresProposalBackend) Get(ctx context.Context, playerID, proposalID string, now time.Time) (domain.Proposal, error) { return store.GetProposal(ctx, p.db, playerID, proposalID, now) } func (p postgresProposalBackend) Respond(ctx context.Context, playerID, proposalID, idempotencyKey string, accept bool, expectedRevision uint64, now time.Time) (domain.Proposal, error) { return store.RespondToProposal(ctx, p.db, playerID, proposalID, idempotencyKey, accept, expectedRevision, now) } func ProposalProviderFromStore(db *sql.DB) ProposalBackend { return postgresProposalBackend{db: db} } // ProposalPromoterFromStore turns a durably accepted proposal into its exact // matcher-selected ALLOCATING match. The store chooses a deterministic match // ID so an API retry after a transient failure cannot duplicate the match. func ProposalPromoterFromStore(db *sql.DB) ProposalPromoter { return ProposalPromoterFunc(func(ctx context.Context, proposal domain.Proposal, now time.Time) error { if proposal.State != domain.Accepted { return domain.ErrIllegalTransition } return store.PromoteStoredAcceptedProposal(ctx, db, proposal.ProposalID, now) }) }