Skip to content

Commit

Permalink
feat: implement fieldmask
Browse files Browse the repository at this point in the history
  • Loading branch information
Wil Simpson committed Jan 1, 2025
1 parent db19048 commit 05f1ea6
Show file tree
Hide file tree
Showing 17 changed files with 292 additions and 176 deletions.
2 changes: 1 addition & 1 deletion api
Submodule api updated 1 files
+1 −1 sro/filter.proto
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ go 1.23.3

require (
ariga.io/atlas-provider-gorm v0.5.0
github.com/ShatteredRealms/go-common-service v0.9.18
github.com/ShatteredRealms/go-common-service v0.9.20
github.com/WilSimpson/gocloak/v13 v13.11.3
github.com/go-faker/faker/v4 v4.5.0
github.com/golang-migrate/migrate/v4 v4.18.1
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1
github.com/jackc/pgx/v5 v5.7.1
github.com/mitranim/gow v0.0.0-20231026105220-af11a6e1e9eb
github.com/onsi/ginkgo/v2 v2.22.1
github.com/onsi/gomega v1.36.1
github.com/onsi/ginkgo/v2 v2.22.2
github.com/onsi/gomega v1.36.2
github.com/solo-io/protoc-gen-openapi v0.2.5
github.com/spf13/cobra-cli v1.3.0
go.mongodb.org/mongo-driver v1.17.1
go.opentelemetry.io/otel v1.33.0
go.uber.org/mock v0.5.0
google.golang.org/genproto/googleapis/api v0.0.0-20241223144023-3abc09e42ca8
google.golang.org/genproto/googleapis/api v0.0.0-20241230172942-26aa7a208def
google.golang.org/grpc v1.69.2
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1
google.golang.org/protobuf v1.36.1
Expand Down Expand Up @@ -287,7 +287,7 @@ require (
golang.org/x/term v0.27.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/tools v0.28.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241230172942-26aa7a208def // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ github.com/ShatteredRealms/go-common-service v0.9.16 h1:+dLwg6Zcs76ULvH3991G7pMk
github.com/ShatteredRealms/go-common-service v0.9.16/go.mod h1:AxfNgvbQ0T/gN3FASOaHlOjL0tEZldyDokLMg1G+V8c=
github.com/ShatteredRealms/go-common-service v0.9.18 h1:uHDB29vwvPjD9nXBshzRIzYsZ5MDXARXah5tkZfiUNw=
github.com/ShatteredRealms/go-common-service v0.9.18/go.mod h1:AxfNgvbQ0T/gN3FASOaHlOjL0tEZldyDokLMg1G+V8c=
github.com/ShatteredRealms/go-common-service v0.9.19 h1:bBNtc8lKC/BiIFHJXHR5la/Z3D0HOt9E35Q/85i2fuI=
github.com/ShatteredRealms/go-common-service v0.9.19/go.mod h1:AxfNgvbQ0T/gN3FASOaHlOjL0tEZldyDokLMg1G+V8c=
github.com/ShatteredRealms/go-common-service v0.9.20 h1:wlXY34D9cxWRScnU7IwCyAdleiYWxlpgshTJQfd4ldA=
github.com/ShatteredRealms/go-common-service v0.9.20/go.mod h1:AxfNgvbQ0T/gN3FASOaHlOjL0tEZldyDokLMg1G+V8c=
github.com/TwiN/go-away v1.6.14 h1:gjFP+6/A36gmj0NpYX0Sz9hrdU0KtHwtNWYnsJgV4fo=
github.com/TwiN/go-away v1.6.14/go.mod h1:d+Gv3XuqjIeFqXYuAIzlyNoDzr1vNsP5B/hRY3u/VLs=
github.com/WilSimpson/gocloak/v13 v13.11.3 h1:5Y2j7x3SD8wnwir2dBEOr6XY2Yo6wPQQ24hfkig6KXA=
Expand Down Expand Up @@ -790,12 +794,16 @@ github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg
github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/ginkgo/v2 v2.22.1 h1:QW7tbJAUDyVDVOM5dFa7qaybo+CRfR7bemlQUN6Z8aM=
github.com/onsi/ginkgo/v2 v2.22.1/go.mod h1:S6aTpoRsSq2cZOd+pssHAlKW/Q/jZt6cPrPlnj4a1xM=
github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
Expand Down Expand Up @@ -1514,10 +1522,14 @@ google.golang.org/genproto/googleapis/api v0.0.0-20241216192217-9240e9c98484 h1:
google.golang.org/genproto/googleapis/api v0.0.0-20241216192217-9240e9c98484/go.mod h1:KRUmxRI4JmbpAm8gcZM4Jsffi859fo5LQjILwuqj9z8=
google.golang.org/genproto/googleapis/api v0.0.0-20241223144023-3abc09e42ca8 h1:st3LcW/BPi75W4q1jJTEor/QWwbNlPlDG0JTn6XhZu0=
google.golang.org/genproto/googleapis/api v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:klhJGKFyG8Tn50enBn7gizg4nXGXJ+jqEREdCWaPcV4=
google.golang.org/genproto/googleapis/api v0.0.0-20241230172942-26aa7a208def h1:0Km0hi+g2KXbXL0+riZzSCKz23f4MmwicuEb00JeonI=
google.golang.org/genproto/googleapis/api v0.0.0-20241230172942-26aa7a208def/go.mod h1:u2DoMSpCXjrzqLdobRccQMc9wrnMAJ1DLng0a2yqM2Q=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484 h1:Z7FRVJPSMaHQxD0uXU8WdgFh8PseLM8Q8NzhnpMrBhQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241230172942-26aa7a208def h1:4P81qv5JXI/sDNae2ClVx88cgDDA6DPilADkG9tYKz8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241230172942-26aa7a208def/go.mod h1:bdAgzvd4kFrpykc5/AC2eLUiegK9T/qxZHD4hXYf/ho=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
Expand Down
28 changes: 28 additions & 0 deletions pkg/model/character/character.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import (
"github.com/ShatteredRealms/character-service/pkg/model/game"
"github.com/ShatteredRealms/character-service/pkg/pb"
commongame "github.com/ShatteredRealms/go-common-service/pkg/model/game"
"github.com/ShatteredRealms/go-common-service/pkg/util"
goaway "github.com/TwiN/go-away"
"github.com/google/uuid"
fieldmask_utils "github.com/mennanov/fieldmask-utils"
)

const (
Expand Down Expand Up @@ -135,6 +137,17 @@ func (c *Character) ToPb() *pb.Character {
return char
}

func (c *Character) ToPbWithMask(paths []string) (*pb.Character, error) {
mask, err := fieldmask_utils.MaskFromPaths(paths, util.PascalCase)
if err != nil {
return nil, err
}

outPb := &pb.Character{}
err = fieldmask_utils.StructToStruct(mask, c.ToPb(), outPb)
return outPb, err
}

func (c Characters) ToPb() *pb.Characters {
resp := &pb.Characters{Characters: make([]*pb.Character, len(c))}
for idx, character := range c {
Expand All @@ -145,3 +158,18 @@ func (c Characters) ToPb() *pb.Characters {

return resp
}

func (c Characters) ToPbWithMask(paths []string) (*pb.Characters, error) {
var err error
resp := &pb.Characters{Characters: make([]*pb.Character, len(c))}
for idx, character := range c {
if character != nil {
resp.Characters[idx], err = character.ToPbWithMask(paths)
if err != nil {
return nil, err
}
}
}

return resp, nil
}
11 changes: 7 additions & 4 deletions pkg/repository/character.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ import (
"context"

"github.com/ShatteredRealms/character-service/pkg/model/character"
"github.com/ShatteredRealms/go-common-service/pkg/pb"
"github.com/google/uuid"
)

type CharacterRepository interface {
GetCharacterById(ctx context.Context, characterId *uuid.UUID) (*character.Character, error)
// GetCharacters gets the of character that matches the provided filters. If more than one character matches the filters, an error is returned.
GetCharacter(ctx context.Context, matchFilters map[string]interface{}) (*character.Character, error)

GetCharacters(ctx context.Context) (character.Characters, error)
GetDeletedCharacters(ctx context.Context) (character.Characters, error)
GetCharactersByOwner(ctx context.Context, ownerId *uuid.UUID) (character.Characters, error)
// GetCharacters gets a list of characters that match the provided filters and returns the total number of characters that match the filters.
// If no characters match the filters, an empty list is returned.
// Deleted characters are only returned if deleted is true, and non-deleted characters if true.
GetCharacters(ctx context.Context, matchFilters map[string]interface{}, queryFilter *pb.QueryFilters, deleted bool) (character.Characters, int, error)

CreateCharacter(ctx context.Context, newCharacter *character.Character) (*character.Character, error)
UpdateCharacter(ctx context.Context, updatedCharacter *character.Character) (*character.Character, error)
Expand Down
113 changes: 56 additions & 57 deletions pkg/repository/character_pgx.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import (
"context"
"errors"
"fmt"
"strings"

"github.com/ShatteredRealms/character-service/pkg/common"
"github.com/ShatteredRealms/character-service/pkg/model/character"
"github.com/ShatteredRealms/go-common-service/pkg/log"
"github.com/ShatteredRealms/go-common-service/pkg/pb"
"github.com/ShatteredRealms/go-common-service/pkg/repository"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
Expand Down Expand Up @@ -128,96 +131,92 @@ func (p *pgxCharacterRepository) DeleteCharactersByOwner(ctx context.Context, ow
return outCharacters, tx.Commit(ctx)
}

// GetCharacterById implements CharacterRepository.
func (p *pgxCharacterRepository) GetCharacterById(ctx context.Context, characterId *uuid.UUID) (*character.Character, error) {
if characterId == nil {
return nil, ErrNilId
func QueryCharacters(ctx context.Context, tx pgx.Tx, matchFilters map[string]interface{}, queryFilter *pb.QueryFilters, deleted bool) (pgx.Rows, int, error) {
total := -1
builder := strings.Builder{}
params := make([]interface{}, 0, len(matchFilters))
builder.WriteString("FROM characters WHERE (deleted_at IS ")
if deleted {
builder.WriteString("NOT NULL")
} else {
builder.WriteString("NULL")
}

tx, err := p.conn.Begin(ctx)
defer tx.Rollback(ctx)
if err != nil {
return nil, err
for key, value := range matchFilters {
builder.WriteString(" AND ")
builder.WriteString(key)
builder.WriteString("=")
builder.WriteString(fmt.Sprintf("$%d", len(params)+1))
params = append(params, value)
}
builder.WriteString(")")

rows, _ := tx.Query(ctx,
"SELECT * FROM characters WHERE id = $1",
characterId)
outCharacter, err := pgx.CollectExactlyOneRow(rows, pgx.RowToAddrOfStructByName[character.Character])
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
if queryFilter != nil {
rows, err := tx.Query(ctx, "SELECT COUNT(*) "+builder.String(), params...)
if err != nil {
return nil, -1, err
}
if rows.Next() {
err = rows.Scan(&total)
rows.Close()
}
return nil, err
}

return outCharacter, tx.Commit(ctx)
}
log.Logger.Infof("total: %d", total)

// GetCharacters implements CharacterRepository.
func (p *pgxCharacterRepository) GetCharacters(ctx context.Context) (character.Characters, error) {
tx, err := p.conn.Begin(ctx)
defer tx.Rollback(ctx)
if err != nil {
return nil, err
}

rows, _ := tx.Query(ctx, "SELECT * FROM characters WHERE deleted_at IS NULL")
outCharacters, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[character.Character])
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
if queryFilter.Limit > 0 {
builder.WriteString(fmt.Sprintf(" LIMIT %d", queryFilter.Limit))
}
if queryFilter.Offset > 0 {
builder.WriteString(fmt.Sprintf(" OFFSET %d", queryFilter.Offset))
}
return nil, err
}

return outCharacters, tx.Commit(ctx)
rows, err := tx.Query(ctx, "SELECT * "+builder.String()+";", params...)
return rows, total, err
}

// GetCharactersByOwner implements CharacterRepository.
func (p *pgxCharacterRepository) GetCharactersByOwner(ctx context.Context, ownerId *uuid.UUID) (character.Characters, error) {
if ownerId == nil {
return nil, ErrNilId
}

// GetCharacter implements CharacterRepository.
func (p *pgxCharacterRepository) GetCharacter(ctx context.Context, matchFilters map[string]interface{}) (*character.Character, error) {
tx, err := p.conn.Begin(ctx)
defer tx.Rollback(ctx)
if err != nil {
return nil, err
}

rows, _ := tx.Query(ctx,
"SELECT * FROM characters WHERE (owner_id = $1 AND deleted_at IS NULL)",
ownerId)
outCharacters, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[character.Character])
rows, _, err := QueryCharacters(ctx, tx, matchFilters, nil, false)
if err != nil {
return nil, err
}
outCharacter, err := pgx.CollectExactlyOneRow(rows, pgx.RowToAddrOfStructByNameLax[character.Character])
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
}
return nil, err
}

return outCharacters, tx.Commit(ctx)
return outCharacter, tx.Commit(ctx)
}

// GetDeletedCharacters implements CharacterRepository.
func (p *pgxCharacterRepository) GetDeletedCharacters(ctx context.Context) (character.Characters, error) {
// GetCharacters implements CharacterRepository.
func (p *pgxCharacterRepository) GetCharacters(ctx context.Context, matchFilters map[string]interface{}, queryFilter *pb.QueryFilters, deleted bool) (character.Characters, int, error) {
tx, err := p.conn.Begin(ctx)
defer tx.Rollback(ctx)
if err != nil {
return nil, err
return nil, -1, err
}

rows, _ := tx.Query(ctx, "SELECT * FROM characters WHERE deleted_at IS NOT NULL")
rows, total, err := QueryCharacters(ctx, tx, matchFilters, queryFilter, deleted)
if err != nil {
return nil, -1, err
}
outCharacters, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[character.Character])
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
return nil, 0, nil
}
return nil, err
return nil, -1, err
}

return outCharacters, tx.Commit(ctx)
return outCharacters, total, tx.Commit(ctx)
}

// UpdateCharacter implements CharacterRepository.
Expand All @@ -233,9 +232,9 @@ func (p *pgxCharacterRepository) UpdateCharacter(ctx context.Context, c *charact
}

rows, _ := tx.Query(ctx,
`UPDATE
characters
SET
`UPDATE
characters
SET
owner_id = $2,
name = $3,
gender = $4,
Expand Down
Loading

0 comments on commit 05f1ea6

Please sign in to comment.