Use hashids for player IDs, drop UUID uses
This commit is contained in:
parent
3e091eb71b
commit
e69ffba5ae
1
go.mod
1
go.mod
|
@ -4,7 +4,6 @@ go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-chi/chi v4.1.2+incompatible
|
github.com/go-chi/chi v4.1.2+incompatible
|
||||||
github.com/gofrs/uuid v3.3.0+incompatible
|
|
||||||
github.com/jessevdk/go-flags v1.4.1-0.20181221193153-c0795c8afcf4
|
github.com/jessevdk/go-flags v1.4.1-0.20181221193153-c0795c8afcf4
|
||||||
github.com/mailru/easyjson v0.7.1
|
github.com/mailru/easyjson v0.7.1
|
||||||
github.com/markbates/pkger v0.17.0
|
github.com/markbates/pkger v0.17.0
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -41,8 +41,6 @@ github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
|
||||||
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||||
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
|
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
|
||||||
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||||
github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84=
|
|
||||||
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
|
14
helpers.go
14
helpers.go
|
@ -1,19 +1,5 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
|
||||||
"github.com/tomwright/queryparam/v4"
|
|
||||||
)
|
|
||||||
|
|
||||||
func stringPtr(s string) *string {
|
func stringPtr(s string) *string {
|
||||||
return &s
|
return &s
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
queryparam.DefaultParser.ValueParsers[reflect.TypeOf(uuid.UUID{})] = func(value string, _ string) (reflect.Value, error) {
|
|
||||||
id, err := uuid.FromString(value)
|
|
||||||
return reflect.ValueOf(id), err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
package game
|
package game
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gofrs/uuid"
|
|
||||||
"github.com/zikaeroh/codies/internal/words"
|
"github.com/zikaeroh/codies/internal/words"
|
||||||
"github.com/zikaeroh/codies/internal/words/static"
|
"github.com/zikaeroh/codies/internal/words/static"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PlayerID = uuid.UUID
|
type PlayerID = string
|
||||||
|
|
||||||
type WordList struct {
|
type WordList struct {
|
||||||
Name string
|
Name string
|
||||||
|
|
|
@ -537,9 +537,7 @@ func easyjsonE4425964DecodeGithubComZikaerohCodiesInternalProtocol6(in *jlexer.L
|
||||||
}
|
}
|
||||||
switch key {
|
switch key {
|
||||||
case "playerID":
|
case "playerID":
|
||||||
if data := in.UnsafeBytes(); in.Ok() {
|
out.PlayerID = string(in.String())
|
||||||
in.AddError((out.PlayerID).UnmarshalText(data))
|
|
||||||
}
|
|
||||||
case "nickname":
|
case "nickname":
|
||||||
out.Nickname = string(in.String())
|
out.Nickname = string(in.String())
|
||||||
case "spymaster":
|
case "spymaster":
|
||||||
|
@ -565,7 +563,7 @@ func easyjsonE4425964EncodeGithubComZikaerohCodiesInternalProtocol6(out *jwriter
|
||||||
{
|
{
|
||||||
const prefix string = ",\"playerID\":"
|
const prefix string = ",\"playerID\":"
|
||||||
out.RawString(prefix[1:])
|
out.RawString(prefix[1:])
|
||||||
out.RawText((in.PlayerID).MarshalText())
|
out.String(string(in.PlayerID))
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const prefix string = ",\"nickname\":"
|
const prefix string = ",\"nickname\":"
|
||||||
|
@ -623,9 +621,7 @@ func easyjsonE4425964DecodeGithubComZikaerohCodiesInternalProtocol7(in *jlexer.L
|
||||||
}
|
}
|
||||||
switch key {
|
switch key {
|
||||||
case "playerID":
|
case "playerID":
|
||||||
if data := in.UnsafeBytes(); in.Ok() {
|
out.PlayerID = string(in.String())
|
||||||
in.AddError((out.PlayerID).UnmarshalText(data))
|
|
||||||
}
|
|
||||||
case "roomState":
|
case "roomState":
|
||||||
if in.IsNull() {
|
if in.IsNull() {
|
||||||
in.Skip()
|
in.Skip()
|
||||||
|
@ -657,7 +653,7 @@ func easyjsonE4425964EncodeGithubComZikaerohCodiesInternalProtocol7(out *jwriter
|
||||||
{
|
{
|
||||||
const prefix string = ",\"playerID\":"
|
const prefix string = ",\"playerID\":"
|
||||||
out.RawString(prefix[1:])
|
out.RawString(prefix[1:])
|
||||||
out.RawText((in.PlayerID).MarshalText())
|
out.String(string(in.PlayerID))
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const prefix string = ",\"roomState\":"
|
const prefix string = ",\"roomState\":"
|
||||||
|
|
|
@ -4,13 +4,13 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
|
||||||
"github.com/speps/go-hashids"
|
|
||||||
"github.com/zikaeroh/codies/internal/game"
|
"github.com/zikaeroh/codies/internal/game"
|
||||||
"github.com/zikaeroh/codies/internal/protocol"
|
"github.com/zikaeroh/codies/internal/protocol"
|
||||||
|
"github.com/zikaeroh/codies/internal/uid"
|
||||||
"github.com/zikaeroh/ctxjoin"
|
"github.com/zikaeroh/ctxjoin"
|
||||||
"github.com/zikaeroh/ctxlog"
|
"github.com/zikaeroh/ctxlog"
|
||||||
"go.uber.org/atomic"
|
"go.uber.org/atomic"
|
||||||
|
@ -33,34 +33,30 @@ type Server struct {
|
||||||
doPrune chan struct{}
|
doPrune chan struct{}
|
||||||
ready chan struct{}
|
ready chan struct{}
|
||||||
|
|
||||||
mu sync.Mutex
|
genRoomID *uid.Generator
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
rooms map[string]*Room
|
rooms map[string]*Room
|
||||||
roomIDs map[string]*Room
|
roomIDs map[string]*Room
|
||||||
|
|
||||||
hid *hashids.HashID
|
|
||||||
nextID int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer() *Server {
|
func NewServer() *Server {
|
||||||
hd := hashids.NewData()
|
|
||||||
hd.MinLength = 8
|
|
||||||
hd.Salt = uuid.Must(uuid.NewV4()).String() // IDs are only valid for this server instance; ok to randomize salt.
|
|
||||||
hid, err := hashids.NewWithData(hd)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Server{
|
return &Server{
|
||||||
ready: make(chan struct{}),
|
ready: make(chan struct{}),
|
||||||
doPrune: make(chan struct{}, 1),
|
doPrune: make(chan struct{}, 1),
|
||||||
|
genRoomID: uid.NewGenerator(salt()), // IDs are only valid for this server instance; ok to randomize salt.
|
||||||
rooms: make(map[string]*Room),
|
rooms: make(map[string]*Room),
|
||||||
roomIDs: make(map[string]*Room),
|
roomIDs: make(map[string]*Room),
|
||||||
hid: hid,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func salt() string {
|
||||||
|
x := time.Now().Unix()
|
||||||
|
return strconv.FormatInt(x, 10)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) Run(ctx context.Context) error {
|
func (s *Server) Run(ctx context.Context) error {
|
||||||
s.ctx = ctx
|
s.ctx = ctx
|
||||||
|
|
||||||
|
@ -113,11 +109,7 @@ func (s *Server) CreateRoom(ctx context.Context, name, password string) (*Room,
|
||||||
return nil, ErrTooManyRooms
|
return nil, ErrTooManyRooms
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := s.hid.EncodeInt64([]int64{s.nextID})
|
id, idRaw := s.genRoomID.Next()
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
s.nextID++
|
|
||||||
|
|
||||||
roomCtx, roomCancel := context.WithCancel(s.ctx)
|
roomCtx, roomCancel := context.WithCancel(s.ctx)
|
||||||
|
|
||||||
|
@ -127,6 +119,7 @@ func (s *Server) CreateRoom(ctx context.Context, name, password string) (*Room,
|
||||||
ID: id,
|
ID: id,
|
||||||
clientCount: &s.clientCount,
|
clientCount: &s.clientCount,
|
||||||
roomCount: &s.roomCount,
|
roomCount: &s.roomCount,
|
||||||
|
genPlayerID: uid.NewGenerator(id),
|
||||||
ctx: roomCtx,
|
ctx: roomCtx,
|
||||||
cancel: roomCancel,
|
cancel: roomCancel,
|
||||||
room: game.NewRoom(nil),
|
room: game.NewRoom(nil),
|
||||||
|
@ -143,9 +136,9 @@ func (s *Server) CreateRoom(ctx context.Context, name, password string) (*Room,
|
||||||
s.roomCount.Inc()
|
s.roomCount.Inc()
|
||||||
metricRooms.Inc()
|
metricRooms.Inc()
|
||||||
|
|
||||||
ctxlog.Info(ctx, "created new room", zap.String("name", name), zap.String("id", room.ID))
|
ctxlog.Info(ctx, "created new room", zap.String("roomName", name), zap.String("roomID", room.ID))
|
||||||
|
|
||||||
if s.nextID%100 == 0 {
|
if idRaw%100 == 0 {
|
||||||
s.triggerPrune()
|
s.triggerPrune()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,6 +200,7 @@ type Room struct {
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
clientCount *atomic.Int64
|
clientCount *atomic.Int64
|
||||||
roomCount *atomic.Int64
|
roomCount *atomic.Int64
|
||||||
|
genPlayerID *uid.Generator
|
||||||
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
room *game.Room
|
room *game.Room
|
||||||
|
@ -225,12 +219,12 @@ type Room struct {
|
||||||
type noteSender func(protocol.ServerNote)
|
type noteSender func(protocol.ServerNote)
|
||||||
|
|
||||||
func (r *Room) HandleConn(ctx context.Context, nickname string, c *websocket.Conn) {
|
func (r *Room) HandleConn(ctx context.Context, nickname string, c *websocket.Conn) {
|
||||||
playerID := uuid.Must(uuid.NewV4())
|
playerID, _ := r.genPlayerID.Next()
|
||||||
|
|
||||||
ctx, cancel := ctxjoin.AddCancel(ctx, r.ctx)
|
ctx, cancel := ctxjoin.AddCancel(ctx, r.ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
ctx = ctxlog.With(ctx, zap.String("roomName", r.Name), zap.String("roomID", r.ID), zap.String("nickname", nickname))
|
ctx = ctxlog.With(ctx, zap.String("roomName", r.Name), zap.String("roomID", r.ID), zap.String("playerID", playerID), zap.String("nickname", nickname))
|
||||||
|
|
||||||
metricClients.Inc()
|
metricClients.Inc()
|
||||||
defer metricClients.Dec()
|
defer metricClients.Dec()
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
// Package uid generates unique IDs.
|
||||||
|
package uid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/speps/go-hashids"
|
||||||
|
"go.uber.org/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Generator generates unique incrementing IDs. These IDs are only comparable
|
||||||
|
// with other IDs from this generator.
|
||||||
|
type Generator struct {
|
||||||
|
hid *hashids.HashID
|
||||||
|
next atomic.Int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGenerator creates a new Generator with the specified salt. Generators
|
||||||
|
// with the same salt generate the same IDs in order.
|
||||||
|
func NewGenerator(salt string) *Generator {
|
||||||
|
hd := hashids.NewData()
|
||||||
|
hd.MinLength = 8
|
||||||
|
hd.Salt = salt
|
||||||
|
hid, err := hashids.NewWithData(hd)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Generator{
|
||||||
|
hid: hid,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next gets the next ID, in both an encoded string form and the raw integer form.
|
||||||
|
func (g *Generator) Next() (string, int64) {
|
||||||
|
v := g.next.Inc()
|
||||||
|
id, err := g.hid.EncodeInt64([]int64{v})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return id, v
|
||||||
|
}
|
Loading…
Reference in New Issue