Skip to content

Commit

Permalink
Implements GetCounter and UpdateCounter on the SDK Server (#3322)
Browse files Browse the repository at this point in the history
* Implements GetCounter and UpdateCounter on the SDK Server

* Adds UpdateCounter SDKServer test

* Changes Update Counter Request to batch and validate in the SDK

* Cleans up duplicate code in sdkserver updateCounter

* Adds a cached version of the GameServer to the SDK
If the GameServer has been successfully updated by the client in the updateCounter this updated version is stored in the SDK. If the s.gameServer() is called and the Generation of the gameServer is less than (older than) the version stored in the SDK, then the SDK version is returned.

* Removes the diffList for counterUpdateRequest
The diff will be a single aggregated number that may be truncated if final Count of the Counter would be less than zero or greater than capacity. This means a request to increment or decrement a Counter may only be partially applied.

* Adds logic to allow for decrementing the Count even when Count is greater than Capacity after decrementation
Also adds tests.

* More tests for updateCounter

* Removes UpdateCounter from the LocalSDK
This logic followed a previous version of the proto for UpdateCounter.

* Adds in debug logs for when the UpdateCounter request truncates requests

* Generated Files

* Removes file that should no longer be generated

* Changes per review comments
Largest change is to truncate any existing Count to the Capacity, so that Count is always less than or equal to Capacity on any change.

* Removing unused swagger model

* Generated files

* Minor updates per review comments

* Updates error messages to follow the Google Style Guide

* Adds debug log for flaky TestGameServerResourceValidation
  • Loading branch information
igooch committed Sep 11, 2023
1 parent d65a506 commit 9deb15f
Show file tree
Hide file tree
Showing 22 changed files with 1,673 additions and 816 deletions.
565 changes: 334 additions & 231 deletions pkg/sdk/alpha/alpha.pb.go

Large diffs are not rendered by default.

58 changes: 13 additions & 45 deletions pkg/sdk/alpha/alpha.pb.gw.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 1 addition & 7 deletions pkg/sdk/alpha/alpha_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/sdk/beta/beta.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/sdk/beta/beta_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/sdk/sdk.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/sdk/sdk_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 3 additions & 49 deletions pkg/sdkserver/localsdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -606,58 +606,12 @@ func (l *LocalSDKServer) GetCounter(ctx context.Context, in *alpha.GetCounterReq
return nil, errors.Errorf("NOT_FOUND. %s Counter not found", in.Name)
}

// UpdateCounter returns the updated Counter. Returns NOT_FOUND if the Counter does not exist (name cannot be updated).
// Returns OUT_OF_RANGE if the Count is out of range [0,Capacity].
// Returns INVALID_ARGUMENT if the field mask path(s) are not field(s) of the Counter.
// If a field mask path(s) is specified, but the value is not set in the request Counter object,
// then the default value for the variable will be set (i.e. 0 for "capacity" or "count").
// UpdateCounter returns the updated Counter.
// [Stage:Alpha]
// [FeatureFlag:CountsAndLists]
func (l *LocalSDKServer) UpdateCounter(ctx context.Context, in *alpha.UpdateCounterRequest) (*alpha.Counter, error) {
if !runtime.FeatureEnabled(runtime.FeatureCountsAndLists) {
return nil, errors.Errorf("%s not enabled", runtime.FeatureCountsAndLists)
}

if in.Counter == nil || in.UpdateMask == nil {
return nil, errors.Errorf("INVALID_ARGUMENT. Counter: %v and UpdateMask %v cannot be nil", in.Counter, in.UpdateMask)
}

l.logger.WithField("name", in.Counter.Name).Info("Updating Counter")
l.recordRequest("updatecounter")
l.gsMutex.Lock()
defer l.gsMutex.Unlock()

// TODO: https://google.aip.dev/134, "Update masks must support a special value *, meaning full replacement."
// Check if the UpdateMask paths are valid, return INVALID_ARGUMENT if not.
if !in.UpdateMask.IsValid(in.Counter.ProtoReflect().Interface()) {
return nil, errors.Errorf("INVALID_ARGUMENT. Field Mask Path(s): %v are invalid for Counter. Use valid field name(s): %v", in.UpdateMask.GetPaths(), in.Counter.ProtoReflect().Descriptor().Fields())
}

// TODO: Pull in variable Max Capacity from CRD instead of hard-coded number here.
if in.Counter.Capacity < 0 || in.Counter.Capacity > 1000 {
return nil, errors.Errorf("OUT_OF_RANGE. Capacity must be within range [0,1000]. Found Capacity: %d", in.Counter.Capacity)
}

name := in.Counter.Name
if counter, ok := l.gs.Status.Counters[name]; ok {
// Create *alpha.Counter from *sdk.GameServer_Status_CounterStatus for merging.
tmpCounter := &alpha.Counter{Name: name, Count: counter.Count, Capacity: counter.Capacity}
// Removes any fields from the request object that are not included in the FieldMask Paths.
fmutils.Filter(in.Counter, in.UpdateMask.Paths)
// Removes any fields from the existing gameserver object that are included in the FieldMask Paths.
fmutils.Prune(tmpCounter, in.UpdateMask.Paths)
// Due due filtering and pruning all gameserver object field(s) contained in the FieldMask are overwritten by the request object field(s).
proto.Merge(tmpCounter, in.Counter)
// Verify that 0 <= Count >= Capacity
if tmpCounter.Count < 0 || tmpCounter.Count > tmpCounter.Capacity {
return nil, errors.Errorf("OUT_OF_RANGE. Count must be within range [0,Capacity]. Found Count: %d, Capacity: %d", tmpCounter.Count, tmpCounter.Capacity)
}
// Write newly updated Counter to gameserverstatus.
l.gs.Status.Counters[name].Count = tmpCounter.Count
l.gs.Status.Counters[name].Capacity = tmpCounter.Capacity
return &alpha.Counter{Name: name, Count: l.gs.Status.Counters[name].Count, Capacity: l.gs.Status.Counters[name].Capacity}, nil
}
return nil, errors.Errorf("NOT_FOUND. %s Counter not found", name)
// TODO(#2716): Implement me
return nil, errors.Errorf("Unimplemented -- UpdateCounter coming soon")
}

// GetList returns a List. Returns NOT_FOUND if the List does not exist.
Expand Down
Loading

0 comments on commit 9deb15f

Please sign in to comment.