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

Serialize StorageReadObjects's in the same way (postgres&cockroachDB) #1066

Closed
wants to merge 2 commits into from
Closed
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
40 changes: 28 additions & 12 deletions server/core_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"errors"
"fmt"
"sort"
"strings"

"github.com/gofrs/uuid/v5"
"github.com/heroiclabs/nakama-common/api"
Expand Down Expand Up @@ -416,10 +417,6 @@ func storageListObjects(rows *sql.Rows, limit int) (*api.StorageObjectList, erro
}

func StorageReadObjects(ctx context.Context, logger *zap.Logger, db *sql.DB, caller uuid.UUID, objectIDs []*api.ReadStorageObjectId) (*api.StorageObjects, error) {
collectionParam := make([]string, 0, len(objectIDs))
keyParam := make([]string, 0, len(objectIDs))
userIdParam := make([]uuid.UUID, 0, len(objectIDs))

// When selecting variable number of object we'd like to keep number of
// SQL query arguments constant, otherwise query statistics explode, because
// from PostgreSQL perspective query with different number of arguments is a distinct query
Expand Down Expand Up @@ -451,9 +448,24 @@ func StorageReadObjects(ctx context.Context, logger *zap.Logger, db *sql.DB, cal
`
}

for _, id := range objectIDs {
collectionParam = append(collectionParam, id.Collection)
keyParam = append(keyParam, id.Key)
collectionParamStr := &strings.Builder{}
collectionParamStr.Grow(2 + len(objectIDs)*128)
collectionParamStr.WriteString("{")
keyParamStr := &strings.Builder{}
keyParamStr.Grow(2 + len(objectIDs)*128)
keyParamStr.WriteString("{")
userIdParamStr := &strings.Builder{}
userIdParamStr.Grow(2 + len(objectIDs)*36)
userIdParamStr.WriteString("{")

for idx, id := range objectIDs {
if idx > 0 {
collectionParamStr.WriteString(",")
keyParamStr.WriteString(",")
userIdParamStr.WriteString(",")
}
collectionParamStr.WriteString(id.Collection)
keyParamStr.WriteString(id.Key)
var reqUid uuid.UUID
if uid := id.GetUserId(); uid != "" {
if uid, err := uuid.FromString(uid); err == nil {
Expand All @@ -463,10 +475,14 @@ func StorageReadObjects(ctx context.Context, logger *zap.Logger, db *sql.DB, cal
return nil, err
}
}
userIdParam = append(userIdParam, reqUid)
userIdParamStr.WriteString(reqUid.String())
}

params := []interface{}{collectionParam, keyParam, userIdParam}
collectionParamStr.WriteString("}")
keyParamStr.WriteString("}")
userIdParamStr.WriteString("}")

params := []interface{}{collectionParamStr.String(), keyParamStr.String(), userIdParamStr.String()}
if caller != uuid.Nil {
params = append(params, caller)
}
Expand Down Expand Up @@ -635,7 +651,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 +678,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 +699,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