fix: make SQL queue recovery expire authoritatively

This commit is contained in:
Josh Creek
2026-08-31 22:14:30 +01:00
parent 068b66b234
commit b2d68d93cf
3 changed files with 14 additions and 4 deletions
+7 -3
View File
@@ -91,15 +91,19 @@ type queueTicketRecord struct {
Revision uint64 `json:"revision"`
}
func GetQueueTicket(ctx context.Context, db *sql.DB, playerID, ticketID string) (domain.QueueTicket, error) {
if db == nil || playerID == "" || ticketID == "" {
func GetQueueTicket(ctx context.Context, db *sql.DB, playerID, ticketID string, now time.Time) (domain.QueueTicket, error) {
if db == nil || playerID == "" || ticketID == "" || now.IsZero() {
return domain.QueueTicket{}, fmt.Errorf("invalid queue recovery arguments")
}
var record queueTicketRecord
if err := db.QueryRowContext(ctx, QueueTicketSelectSQL, ticketID, playerID).Scan(&record.TicketID, &record.PlayerID, &record.Playlist, &record.State, &record.ClientBuild, &record.ProtocolVersion, &record.EnqueuedAt, &record.ExpiresAt, &record.Revision); err != nil {
return domain.QueueTicket{}, err
}
return queueTicketRecordToDomain(record), nil
ticket := queueTicketRecordToDomain(record)
if (ticket.State == domain.Queued || ticket.State == domain.Proposed) && !now.Before(ticket.ExpiresAt) {
return domain.QueueTicket{}, domain.ErrTicketExpired
}
return ticket, nil
}
func HeartbeatQueueTicket(ctx context.Context, db *sql.DB, playerID, ticketID, idempotencyKey string, expectedRevision uint64, now time.Time) (domain.QueueTicket, error) {
+6
View File
@@ -38,3 +38,9 @@ func TestCreateQueueTicketRejectsInvalidArgumentsWithoutDatabase(t *testing.T) {
t.Fatal("invalid arguments accepted")
}
}
func TestQueueRecoveryRequiresAuthoritativeClock(t *testing.T) {
if _, err := GetQueueTicket(nil, nil, "player-1", "ticket-1", time.Time{}); err == nil {
t.Fatal("recovery without a clock was accepted")
}
}