Skip to content

Commit

Permalink
Implement block on connect with Rust SDK
Browse files Browse the repository at this point in the history
- Uses a simple polling mechanism to confirm the connection is live
- Tweaks the conformance tests to add a random delay to ensure future
  testing of SDK blocking.
- Add `ready` to the SDK documentation.

Fixes googleforgames#938
  • Loading branch information
markmandel committed Jul 27, 2019
1 parent c82add5 commit 5902a38
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 12 deletions.
14 changes: 11 additions & 3 deletions build/includes/sdk.mk
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,17 @@ run-sdk-conformance-local: ensure-agones-sdk-image
-e "TEST=$(TESTS)" -e "TIMEOUT=$(TIMEOUT)" $(sidecar_tag)

# Run SDK conformance test, previously built, for a specific SDK_FOLDER
# Sleeps the start of the sidecar to test that the SDK blocks on connection correctly
run-sdk-conformance-no-build: TIMEOUT ?= 30
run-sdk-conformance-no-build: RANDOM := $(shell bash -c 'echo $$RANDOM')
run-sdk-conformance-no-build: DELAY ?= $(shell bash -c "echo $$[ ($(RANDOM) % 5 ) + 1 ]s")
run-sdk-conformance-no-build: TESTS ?= ready,allocate,setlabel,setannotation,gameserver,health,shutdown,watch
run-sdk-conformance-no-build: ensure-agones-sdk-image
run-sdk-conformance-no-build: ensure-build-sdk-image
sleep 2s && DOCKER_RUN_ARGS="--network=host $(DOCKER_RUN_ARGS)" COMMAND=sdktest $(MAKE) run-sdk-command & \
docker run -p 59357:59357 -e "ADDRESS=" \
DOCKER_RUN_ARGS="--network=host $(DOCKER_RUN_ARGS)" COMMAND=sdktest $(MAKE) run-sdk-command & \
sleep $(DELAY) && docker run -p 59357:59357 -e "ADDRESS=" \
-e "TEST=$(TESTS)" -e "TIMEOUT=$(TIMEOUT)" --net=host $(sidecar_tag)


# Run SDK conformance test for a specific SDK_FOLDER
run-sdk-conformance-test:
$(MAKE) run-sdk-command COMMAND=build-sdk-test
Expand All @@ -142,3 +144,9 @@ run-sdk-conformance-tests:
$(MAKE) run-sdk-conformance-test SDK_FOLDER=node
$(MAKE) run-sdk-conformance-test SDK_FOLDER=go TESTS=ready,allocate,setlabel,setannotation,gameserver,health,shutdown,watch,reserve
$(MAKE) run-sdk-conformance-test SDK_FOLDER=rust

RANDOM := $(shell bash -c 'echo $$RANDOM')
DELAY ?= $(shell bash -c "echo $$[ ($(RANDOM) % 5 ) + 1 ]s")
debug:
echo $(DELAY)

34 changes: 26 additions & 8 deletions sdks/rust/src/sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use futures::{Future, Sink, Stream};
use grpcio;
use std::sync::{Arc, Mutex};
use std::thread::sleep;
use std::time::Duration;

use futures::{Future, Sink, Stream};
use grpcio;
use grpcio::CallOption;
use protobuf::Message;

use errors::*;
use grpc::sdk;
use grpc::sdk_grpc;
use protobuf::Message;
use types::*;

const PORT: i32 = 59357;
Expand All @@ -34,7 +37,7 @@ pub struct Sdk {
impl Sdk {
/// Starts a new SDK instance, and connects to localhost on port 59357.
/// Blocks until connection and handshake are made.
/// Times out after 30 seconds.
/// Times out after ~30 seconds.
pub fn new() -> Result<Sdk> {
let addr = format!("localhost:{}", PORT);
let env = Arc::new(grpcio::EnvBuilder::new().build());
Expand All @@ -43,7 +46,24 @@ impl Sdk {
.connect(&addr);
let cli = sdk_grpc::SdkClient::new(ch);
let req = sdk::Empty::new();
let _ = cli.ready(&req).map(Box::new)?;

// Unfortunately there isn't a native way to block until connected
// so we had to roll our own.
let mut counter = 0;
loop {
counter += 1;
match cli.get_game_server(&req) {
Ok(_) => break,
Err(e) => {
if counter > 30 {
return Err(ErrorKind::Grpc(e).into());
}
sleep(Duration::from_secs(1));
continue;
}
}
}

let (sender, _) = cli.health()?;
Ok(Sdk {
client: Arc::new(cli),
Expand All @@ -58,15 +78,13 @@ impl Sdk {
Ok(res)
}


/// Allocate the Game Server
/// Allocate the Game Server
pub fn allocate(&self) -> Result<()> {
let req = sdk::Empty::default_instance();
let res = self.client.allocate(req).map(|_| ())?;
Ok(res)
}


/// Marks the Game Server as ready to shutdown
pub fn shutdown(&self) -> Result<()> {
let req = sdk::Empty::default_instance();
Expand Down
9 changes: 9 additions & 0 deletions site/content/en/docs/Guides/Client SDKs/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ if sdk.health().is_ok() {
}
```

{{% feature publishVersion="0.12.0" %}}

To mark the [game session as ready]({{< relref "_index.md#ready" >}}) call `sdk.ready()`.

```rust
if sdk.ready()?
```
{{% /feature %}}

To mark that the [game session is completed]({{< relref "_index.md#shutdown" >}}) and the game server should be shut down call `sdk.shutdown()`.

```rust
Expand Down
16 changes: 16 additions & 0 deletions test/sdk/rust/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright 2017 Google LLC All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

/target/
Cargo.lock
2 changes: 1 addition & 1 deletion test/sdk/rust/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ fn run() -> Result<(), String> {
thread::sleep(Duration::from_secs(5));
}

println!("Shutting down after 20 seconds...");
println!("Shutting down...");
sdk.shutdown()
.map_err(|e| format!("Could not run Shutdown: {}. Exiting!", e))?;
println!("...marked for Shutdown");
Expand Down

0 comments on commit 5902a38

Please sign in to comment.