Game maintenance
Introduction
Running regular scheduled maintenance on a game world is a common task when you have a deployment running 24 hours a day. Previously the only tools to do this were the SpatialOS CLI and the Console (see Scheduled maintenance). Now you can write your own automated script using the Platform SDK.
In this scenario you’ll need an active running deployment to start with, and you’ll end with a different active running deployment. For this example we’re setting up the first deployment with Setup()
and stopping the second deployment with Cleanup()
.
Find out how to download the Platform SDK from the setup guide.
Example: setting up game maintenance for a deployment
1. Instantiate clients
Instantiate clients of the DeploymentServiceClient
and SnapshotServiceClient
types.
Use the Create
method of the DeploymentServiceClient
and SnapshotServiceClient
.
private static readonly DeploymentServiceClient DeploymentServiceClient = DeploymentServiceClient.Create();
private static readonly SnapshotServiceClient SnapshotServiceClient = SnapshotServiceClient.Create();
By default, it uses your refresh token saved locally by the SpatialOS CLI:
- Windows:
C:\Users\<username>\AppData\Local\.improbable\oauth2\oauth2_refresh_token\
- Mac:
~/.improbable/oauth2/oauth2_refresh_token
If you want to provide a refresh token, you can instantiate a PlatformRefreshTokenCredential
object and supply it to create
:
var credentialsWithProvidedToken = new PlatformRefreshTokenCredential("my_refresh_token");
private static readonly DeploymentServiceClient DeploymentServiceClient = DeploymentServiceClient.Create(credentials: credentialsWithProvidedToken);
private static readonly SnapshotServiceClient SnapshotServiceClient = SnapshotServiceClient.Create(credentials: credentialsWithProvidedToken);
2. List deployments using the project name and deployment name
Retrieve the first deployment entry in the returned list that has the status Running
and the deployment tag my_live_tag
:
var currentLiveDeployment = DeploymentServiceClient
.ListDeployments(new ListDeploymentsRequest
{
ProjectName = "my_project",
DeploymentName = "my_deployment"
})
.First(d => d.Status == Deployment.Types.Status.Running && d.Tag.Contains("my_live_tag"));
3. Remove my_live_tag
and mark deployment as in maintenance
You can use deployment tags to identify attributes like environment (such as production or testing) or whether a deployment is part of the live game. In this case, we’re removing the tag my_live_tag
to indicate that this is no longer a live deployment and players should not be directed towards it:
currentLiveDeployment.Tag.Remove("my_live_tag");
Next, set the worker flags to have a maintenance
value of true
or any other pairs of your choosing for a particular worker type. This lets all workers of that type in the deployment know that the deployment is entering maintenance mode and they should stop performing game updates. Send that update with a call to UpdateDeployment
:
currentLiveDeployment.WorkerFlags.Add(new WorkerFlag
{
Key = "maintenance",
Value = "true",
WorkerType = "unity"
});
DeploymentServiceClient.UpdateDeployment(new UpdateDeploymentRequest {Deployment = currentLiveDeployment});
4. Take a snapshot of the currently running game
This can take some time, so use the PollUntilCompleted
method and wait until it’s completed:
var latestSnapshot = SnapshotServiceClient.TakeSnapshot(new TakeSnapshotRequest
{
Snapshot = new Snapshot
{
ProjectName = currentLiveDeployment.ProjectName,
DeploymentName = currentLiveDeployment.Name
}
}).PollUntilCompleted()
.GetResultOrNull();
5. Stop the deployment using its ID and the project name
DeploymentServiceClient.StopDeployment(new StopDeploymentRequest
{
Id = currentLiveDeployment.Id,
ProjectName = currentLiveDeployment.ProjectName
});
The ID is a universally unique identifier for a particular run of a deployment.
6. Reuse the latest snapshot from the old deployment to start a new deployment
After cloning the deployment object, set the ID of the snapshot that was previously taken to restart at the same game state. All deployment tags and worker flags are cleared before starting the deployment to start with a clean slate. Once the deployment is up and running it can then be updated with the live tag.
var newDeployment = currentLiveDeployment.Clone();
newDeployment.StartingSnapshotId = latestSnapshot.Id;
newDeployment.Tag.Clear();
newDeployment.WorkerFlags.Clear();
newDeployment = DeploymentServiceClient
.CreateDeployment(new CreateDeploymentRequest {Deployment = newDeployment})
.PollUntilCompleted()
.GetResultOrNull();
newDeployment.Tag.Add("my_live_tag");
DeploymentServiceClient.UpdateDeployment(new UpdateDeploymentRequest {Deployment = newDeployment});
You may also choose to edit the snapshot before restarting your deployment. You can do this by converting the snapshot to text and back by running spatial project history snapshot convert
. You can then upload the snapshot and use it to create the new deployment.