Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

storage: switch to native UUID type in StorageWrite #1063

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ require (
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 // indirect
golang.org/x/net v0.12.0 // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/text v0.11.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 h1:Di6/M8l0O2lCLc6VVRWhgCiApHV8MnQurBnFSHsQtNY=
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
Expand Down
7 changes: 4 additions & 3 deletions server/api_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,13 @@ func (s *ApiServer) ReadStorageObjects(ctx context.Context, in *api.ReadStorageO
}

func (s *ApiServer) WriteStorageObjects(ctx context.Context, in *api.WriteStorageObjectsRequest) (*api.StorageObjectAcks, error) {
userID := ctx.Value(ctxUserIDKey{}).(uuid.UUID).String()
userID := ctx.Value(ctxUserIDKey{}).(uuid.UUID)
userIDStr := userID.String()

// Before hook.
if fn := s.runtime.BeforeWriteStorageObjects(); fn != nil {
beforeFn := func(clientIP, clientPort string) error {
result, err, code := fn(ctx, s.logger, userID, ctx.Value(ctxUsernameKey{}).(string), ctx.Value(ctxVarsKey{}).(map[string]string), ctx.Value(ctxExpiryKey{}).(int64), clientIP, clientPort, in)
result, err, code := fn(ctx, s.logger, userIDStr, ctx.Value(ctxUsernameKey{}).(string), ctx.Value(ctxVarsKey{}).(map[string]string), ctx.Value(ctxExpiryKey{}).(int64), clientIP, clientPort, in)
if err != nil {
return status.Error(code, err.Error())
}
Expand Down Expand Up @@ -225,7 +226,7 @@ func (s *ApiServer) WriteStorageObjects(ctx context.Context, in *api.WriteStorag
// After hook.
if fn := s.runtime.AfterWriteStorageObjects(); fn != nil {
afterFn := func(clientIP, clientPort string) error {
return fn(ctx, s.logger, userID, ctx.Value(ctxUsernameKey{}).(string), ctx.Value(ctxVarsKey{}).(map[string]string), ctx.Value(ctxExpiryKey{}).(int64), clientIP, clientPort, acks, in)
return fn(ctx, s.logger, userIDStr, ctx.Value(ctxUsernameKey{}).(string), ctx.Value(ctxVarsKey{}).(map[string]string), ctx.Value(ctxExpiryKey{}).(int64), clientIP, clientPort, acks, in)
}

// Execute the after function lambda wrapped in a trace for stats measurement.
Expand Down
4 changes: 2 additions & 2 deletions server/console_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ func (s *ConsoleServer) WriteStorageObject(ctx context.Context, in *console.Writ
if in.Key == "" {
return nil, status.Error(codes.InvalidArgument, "Requires a valid key.")
}
_, err := uuid.FromString(in.UserId)
userID, err := uuid.FromString(in.UserId)
if err != nil {
return nil, status.Error(codes.InvalidArgument, "Requires a valid user ID.")
}
Expand All @@ -336,7 +336,7 @@ func (s *ConsoleServer) WriteStorageObject(ctx context.Context, in *console.Writ

acks, code, err := StorageWriteObjects(ctx, s.logger, s.db, s.metrics, s.storageIndex, true, StorageOpWrites{
&StorageOpWrite{
OwnerID: in.UserId,
OwnerID: userID,
Object: &api.WriteStorageObject{
Collection: in.Collection,
Key: in.Key,
Expand Down
10 changes: 6 additions & 4 deletions server/console_storage_import.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ func importStorageJSON(ctx context.Context, logger *zap.Logger, db *sql.DB, metr
}

for i, d := range importedData {
if _, err := uuid.FromString(d.UserID); err != nil {
userID, err := uuid.FromString(d.UserID)
if err != nil {
return fmt.Errorf("invalid user ID on object #%d", i)
}

Expand Down Expand Up @@ -184,7 +185,7 @@ func importStorageJSON(ctx context.Context, logger *zap.Logger, db *sql.DB, metr
}

ops = append(ops, &StorageOpWrite{
OwnerID: d.UserID,
OwnerID: userID,
Object: &api.WriteStorageObject{
Collection: d.Collection,
Key: d.Key,
Expand Down Expand Up @@ -255,7 +256,8 @@ func importStorageCSV(ctx context.Context, logger *zap.Logger, db *sql.DB, metri
}
} else {
user := record[columnIndexes["user_id"]]
if _, err := uuid.FromString(user); err != nil {
userID, err := uuid.FromString(user)
if err != nil {
return fmt.Errorf("invalid user ID on row #%d", len(ops)+1)
}
collection := record[columnIndexes["collection"]]
Expand Down Expand Up @@ -283,7 +285,7 @@ func importStorageCSV(ctx context.Context, logger *zap.Logger, db *sql.DB, metri
}

ops = append(ops, &StorageOpWrite{
OwnerID: user,
OwnerID: userID,
Object: &api.WriteStorageObject{
Collection: collection,
Key: key,
Expand Down
14 changes: 8 additions & 6 deletions server/core_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import (
"fmt"
"sort"

"golang.org/x/exp/slices"

"github.com/gofrs/uuid/v5"
"github.com/heroiclabs/nakama-common/api"
"github.com/heroiclabs/nakama-common/runtime"
Expand All @@ -47,7 +49,7 @@ type storageCursor struct {
type StorageOpWrites []*StorageOpWrite

type StorageOpWrite struct {
OwnerID string
OwnerID uuid.UUID
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the gist of this PR

Object *api.WriteStorageObject
}

Expand Down Expand Up @@ -87,7 +89,7 @@ func (s StorageOpWrites) Less(i, j int) bool {
if s1.Object.Key != s2.Object.Key {
return s1.Object.Key < s2.Object.Key
}
return s1.OwnerID < s2.OwnerID
return slices.Compare(s1.OwnerID.Bytes(), s2.OwnerID.Bytes()) == -1
}

// Internal representation for a batch of storage delete operations.
Expand Down Expand Up @@ -598,7 +600,7 @@ func storageWriteObjects(ctx context.Context, logger *zap.Logger, metrics Metric
Collection: object.Collection,
Key: object.Key,
Version: resultVersion,
UserId: op.OwnerID,
UserId: op.OwnerID.String(),
}
acks[indexedOps[op]] = ack
}
Expand Down Expand Up @@ -635,7 +637,7 @@ func storagePrepBatch(batch *pgx.Batch, authoritativeWrite bool, op *StorageOpWr
query = `
WITH upd AS (
UPDATE storage SET value = $4, version = $5, read = $6, write = $7, update_time = now()
WHERE collection = $1 AND key = $2 AND user_id = $3::UUID AND version = $8
WHERE collection = $1 AND key = $2 AND user_id = $3 AND version = $8
` + writeCheck + `
AND NOT (storage.version = $5 AND storage.read = $6 AND storage.write = $7) -- micro optimization: don't update row unnecessary
RETURNING read, write, version
Expand All @@ -662,7 +664,7 @@ func storagePrepBatch(batch *pgx.Batch, authoritativeWrite bool, op *StorageOpWr
query = `
WITH upd AS (
INSERT INTO storage (collection, key, user_id, value, version, read, write, create_time, update_time)
VALUES ($1, $2, $3::UUID, $4, $5, $6, $7, now(), now())
VALUES ($1, $2, $3, $4, $5, $6, $7, now(), now())
ON CONFLICT (collection, key, user_id) DO
UPDATE SET value = $4, version = $5, read = $6, write = $7, update_time = now()
WHERE TRUE` + writeCheck + `
Expand All @@ -683,7 +685,7 @@ func storagePrepBatch(batch *pgx.Batch, authoritativeWrite bool, op *StorageOpWr
// Existing permission checks are not applicable for new storage objects.
query = `
INSERT INTO storage (collection, key, user_id, value, version, read, write, create_time, update_time)
VALUES ($1, $2, $3::UUID, $4, $5, $6, $7, now(), now())
VALUES ($1, $2, $3, $4, $5, $6, $7, now(), now())
RETURNING read, write, version`

// Outcomes:
Expand Down
Loading