package redisstate import ( "encoding/json" "fmt" "time" "galaxy/lobby/internal/domain/application" "galaxy/lobby/internal/domain/common" ) // applicationRecord stores the strict Redis JSON shape used for one // application record. type applicationRecord struct { ApplicationID string `json:"application_id"` GameID string `json:"game_id"` ApplicantUserID string `json:"applicant_user_id"` RaceName string `json:"race_name"` Status application.Status `json:"status"` CreatedAtMS int64 `json:"created_at_ms"` DecidedAtMS *int64 `json:"decided_at_ms,omitempty"` } // MarshalApplication encodes record into the strict Redis JSON shape // used for application records. The record is re-validated before // marshalling. func MarshalApplication(record application.Application) ([]byte, error) { if err := record.Validate(); err != nil { return nil, fmt.Errorf("marshal redis application record: %w", err) } stored := applicationRecord{ ApplicationID: record.ApplicationID.String(), GameID: record.GameID.String(), ApplicantUserID: record.ApplicantUserID, RaceName: record.RaceName, Status: record.Status, CreatedAtMS: record.CreatedAt.UTC().UnixMilli(), DecidedAtMS: optionalUnixMilli(record.DecidedAt), } payload, err := json.Marshal(stored) if err != nil { return nil, fmt.Errorf("marshal redis application record: %w", err) } return payload, nil } // UnmarshalApplication decodes payload from the strict Redis JSON shape // used for application records. The decoded record is validated before // returning. func UnmarshalApplication(payload []byte) (application.Application, error) { var stored applicationRecord if err := decodeStrictJSON("decode redis application record", payload, &stored); err != nil { return application.Application{}, err } record := application.Application{ ApplicationID: common.ApplicationID(stored.ApplicationID), GameID: common.GameID(stored.GameID), ApplicantUserID: stored.ApplicantUserID, RaceName: stored.RaceName, Status: stored.Status, CreatedAt: time.UnixMilli(stored.CreatedAtMS).UTC(), DecidedAt: inflateOptionalTime(stored.DecidedAtMS), } if err := record.Validate(); err != nil { return application.Application{}, fmt.Errorf("decode redis application record: %w", err) } return record, nil }