Skip to content

Commit

Permalink
Adds incrementCounter to cSharp SDK
Browse files Browse the repository at this point in the history
  • Loading branch information
igooch committed Jan 12, 2024
1 parent 5117703 commit c8e729f
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 9 deletions.
4 changes: 2 additions & 2 deletions build/includes/sdk.mk
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ ALPHA_CONFORMANCE_TESTS = getplayercapacity,setplayercapacity,playerconnect,play
# TODO: Move Counter and List tests into ALPHA_CONFORMANCE_TESTS once the they are written for all SDKs
COUNTS_AND_LISTS_TESTS = getcounter,updatecounter,setcountcounter,setcapacitycounter,getlist,updatelist,addlistvalue,removelistvalue
# TODO: Remove
COUNTERS_TESTS = getcounter
COUNTERS_TESTS = getcounter,updatecounter

.PHONY: test-sdks test-sdk build-sdks build-sdk gen-all-sdk-grpc gen-sdk-grpc run-all-sdk-command run-sdk-command build-example

Expand Down Expand Up @@ -187,7 +187,7 @@ run-sdk-conformance-test-rust:

run-sdk-conformance-test-csharp:
# run without feature flags
$(MAKE) run-sdk-conformance-test SDK_FOLDER=csharp GRPC_PORT=9005 HTTP_PORT=9105
# $(MAKE) run-sdk-conformance-test SDK_FOLDER=csharp GRPC_PORT=9005 HTTP_PORT=9105
# run with feature flags enabled
$(MAKE) run-sdk-conformance-test SDK_FOLDER=csharp GRPC_PORT=9005 HTTP_PORT=9105 FEATURE_GATES=$(ALPHA_FEATURE_GATES) TESTS=$(DEFAULT_CONFORMANCE_TESTS),$(ALPHA_CONFORMANCE_TESTS),$(COUNTERS_TESTS)

Expand Down
38 changes: 35 additions & 3 deletions sdks/csharp/sdk/Alpha.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,41 @@ public async Task<long> GetCounterCountAsync(string key)
}
catch (RpcException ex)
{
LogError(ex, "Unable to invoke GetCounterCount.");
throw;
}
LogError(ex, $"Unable to invoke GetCounterCount({key}).");
throw;
}
}

/// <summary>
/// IncrementCounterAsync increases a counter by the given nonnegative integer amount.
/// Will execute the increment operation against the current CRD value. Will max at max(int64).
/// Will error if the key was not predefined in the GameServer resource on creation.
/// Returns false if the count is at the current capacity (to the latest knowledge of the SDK),
/// and no increment will occur.
///
/// Note: A potential race condition here is that if count values are set from both the SDK and
/// through the K8s API (Allocation or otherwise), since the SDK append operation back to the CRD
/// value is batched asynchronous any value incremented past the capacity will be silently truncated.
/// </summary>
/// <returns>True if the increment counter request was successful.</returns>
public async Task<bool> IncrementCounterAsync(string key, long amount)
{
try
{
var request = new CounterUpdateRequest();
request.Name = key;
request.CountDiff = amount;
var updateRequest = new UpdateCounterRequest();
updateRequest.CounterUpdateRequest = request;
var response = await client.UpdateCounterAsync(updateRequest,
deadline: DateTime.UtcNow.AddSeconds(RequestTimeoutSec), cancellationToken: ctoken);
return true;
}
catch (RpcException ex)
{
LogError(ex, $"Unable to invoke IncrementCounter({key}, {amount}).");
throw;
}
}

public void Dispose()
Expand Down
1 change: 1 addition & 0 deletions sdks/csharp/sdk/IAgonesAlphaSDK.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ public interface IAgonesAlphaSDK : IDisposable
Task<bool> IsPlayerConnectedAsync(string id);
Task<List<string>> GetConnectedPlayersAsync();
Task<long> GetCounterCountAsync(string key);
Task<bool> IncrementCounterAsync(string key, long amount);
}
}
36 changes: 33 additions & 3 deletions sdks/csharp/test/AgonesAlphaSDKClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,41 @@ public async Task GetCounterCountAsync_Sends_OK()
// https://grpc.github.io/grpc/csharp/api/Grpc.Core.AsyncUnaryCall-1.html
// public AsyncUnaryCall(Task<TResponse> responseAsync, Task<Metadata> responseHeadersAsync, Func<Status> getStatusFunc, Func<Metadata> getTrailersFunc, Action disposeAction)
mockClient.Setup(m => m.GetCounterAsync(It.IsAny<GetCounterRequest>(), It.IsAny<Metadata>(), It.IsAny<DateTime?>(), It.IsAny<CancellationToken>())).Returns(
(GetCounterRequest _, Metadata _, DateTime? _, CancellationToken _) => new AsyncUnaryCall<Counter>(Task.FromResult(expected), Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { }));
(GetCounterRequest _, Metadata _, DateTime? _, CancellationToken _) =>
new AsyncUnaryCall<Counter>(Task.FromResult(expected), Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { }));
mockSdk.alpha.client = mockClient.Object;

var result = await mockSdk.Alpha().GetCounterCountAsync(key);
Assert.AreEqual(wantCount, result);
var response = await mockSdk.Alpha().GetCounterCountAsync(key);
Assert.AreEqual(wantCount, response);
}

[TestMethod]
public async Task IncrementCounterAsync_Sends_OK()
{
var mockClient = new Mock<SDK.SDKClient>();
var mockSdk = new AgonesSDK();
var key = "counterKey";
var amount = 9;
static Task<Counter> incrementCount(string key, long amount)
{
var counter = new Counter();
counter.Name = key;
counter.Count = 1;
counter.Capacity = 10;
counter.Count += amount;
return Task.FromResult(counter);
}
// TODO: I'm not sure what the point of this test is if we're just mocking the output?
// I.e. this is better tested by test/sdk/csharp/Program.cs which actually makes a call to the local SDK server
mockClient.Setup(m => m.UpdateCounterAsync(It.IsAny<UpdateCounterRequest>(), It.IsAny<Metadata>(),
It.IsAny<DateTime?>(), It.IsAny<CancellationToken>())).Returns(
(UpdateCounterRequest req, Metadata _, DateTime? _, CancellationToken _) =>
new AsyncUnaryCall<Counter>(incrementCount(req.CounterUpdateRequest.Name, req.CounterUpdateRequest.CountDiff),
Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { }));
mockSdk.alpha.client = mockClient.Object;

var response = await mockSdk.Alpha().IncrementCounterAsync(key, amount);
Assert.AreEqual(true, response);
}

[TestMethod]
Expand Down
17 changes: 16 additions & 1 deletion test/sdk/csharp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,12 @@
}

if (featureGates.Contains("CountsAndLists"))
// Tests are expected to run sequentially
{
var alpha = sdk.Alpha();
var key = "conformanceTestCounter";

{
var key = "conformanceTestCounter";
var wantCount = 1;
// TODO: catch expections
var gotCount = await alpha.GetCounterCountAsync(key);
Expand All @@ -180,6 +182,19 @@
Environment.Exit(1);
}
}

{
var wantCount = 10;
var increment = 9;
// TODO: catch expections
await alpha.IncrementCounterAsync(key, increment);
var gotCount = await alpha.GetCounterCountAsync(key);
if (wantCount != gotCount)
{
Console.Error.WriteLine($"Counter count should be {wantCount}, but is {gotCount}");
Environment.Exit(1);
}
}
}

var shutDownStatus = await sdk.ShutDownAsync();
Expand Down

0 comments on commit c8e729f

Please sign in to comment.