This content is not the latest documentation. Please visit our new documentation.

Microstorages

Save state in the cloud

Microstorages

Beamable Microstorages are mongo databases that integrate seamlessly with Beamable Microservices to provide powerful custom state management solutions. Microstorages have a C# project written in dotnet that represents the storage database. This C# project is used as identity, and can be a place to put data related code, such as model types. Beamable Microservices can access storage objects through the Storages accessor.


The gist of a common example Microstorage and Microservice is below.

UserDataStorage

A custom child of MongoStorageObject is defined to wrap the database. The UserMessage is added as the high-level object to be stored in the database.

using Beamable.Server;
using MongoDB.Bson;

namespace Beamable.Server
{
    [StorageObject("UserDataStorage")]
    public class UserDataStorage : MongoStorageObject
    {

    }

    public class UserMessage
    {
        public ObjectId Id;
        public string Message;
        public int X;
        public int Y;
    }
}

UserDataService

The Beamable Microservice UserDataService is created to wrap all calls to the database.

See Microservices for more info.

using System;
using System.Collections.Generic;
using System.Linq;
using MongoDB.Driver;
using UnityEngine;

namespace Beamable.Server
{
   [Microservice("UserDataService")]
   public class UserDataService : Microservice
   {
      [ClientCallable]
      public async Promise<bool> SaveMessage(string message, int x, int y)
      {
         bool isSuccess = false;

         try
         {
            var db = await Storage.GetDatabase<UserDataStorage>();
            var collection = db.GetCollection<UserMessage>("messages");
            collection.InsertOne( new UserMessage()
            {
               Message = message,
               X = x,
               Y = y
            });
            
            isSuccess = true;
         }
         catch (Exception e)
         {
            Debug.LogError(e.Message);
         }

         return isSuccess;
      }
      
      [ClientCallable]
      public async Promise<List<string>> GetMessage(int x, int y)
      {
         var db = await Storage.GetDatabase<UserDataStorage>();
         var collection = db.GetCollection<UserMessage>("messages");
         var messages = collection
            .Find(document => document.X == x && document.Y == y)
            .ToList();

         return messages.Select(m => m.Message).ToList();
      }
   }
}

UserDataMicroServiceExample

using System.Collections.Generic;
using UnityEngine;
using Beamable.Server.Clients;

namespace Beamable.Examples.Features.Microservices.UserDataMicroServiceExample
{
    /// <summary>
    /// Demonstrates <see cref="Microservices"/>.
    /// </summary>
public class UserDataMicroServiceExample : MonoBehaviour
{
    //  Properties  -----------------------------------
        
    //  Fields  ---------------------------------------
    private UserDataServiceClient _userDataServiceClient = null;
        
    //  Unity Methods  --------------------------------

    protected void Start()
    {
        Debug.Log("Start() Instructions...\n" + 
        "* Complete docker setup per https://docs.beamable.com/docs/microservices-feature-overview\n" +
        "* Start the server per https://docs.beamable.com/docs/microservices-feature-overview\n" +
        "* Play This Scene\n" + 
        "* View the Unity Console output\n" + 
        "* Enjoy!\n\n\n");
            
        SetupBeamable();
    }
        
        //  Methods  --------------------------------------
        private async void SetupBeamable()
        {
            var beamContext = BeamContext.Default;
            await beamContext.OnReady;

            Debug.Log($"beamContext.PlayerId = {beamContext.PlayerId}");
            
            _userDataServiceClient = new UserDataServiceClient();
            
            // #1 - Call Microservice
            bool isSuccess = await _userDataServiceClient.SaveMessage("Hello World!", 0, 0);
                
            // #2 - Result = true
            Debug.Log ($"SaveMessage() isSuccess = {isSuccess}");
            
            // #3 - Call Microservice
            List<string> messages = await _userDataServiceClient.GetMessage(0, 0);
                
            // #4 - Result = true
            Debug.Log ($"GetMessage() messages.Count = {messages.Count}, messages[0] = {messages[0]}");
        }
    }
}

Common Practices

To make interactions with mongo storage feature easier and more affordable we've introduced MongoCrudExtensions class that contains following methods:

  • Get
  • Create
  • Update
  • Delete

Example

In the example, there is a TestDocument storage document as described below.

namespace Beamable.Server
{
	public class TestDocument : StorageDocument
	{
		public int IntValue;
		public string StringValue;
	}
}

The example targets the TestStorage StorageObject class.

using Beamable.Common;
using MongoDB.Driver;

namespace Beamable.Server
{
	[StorageObject("TestStorage")]
	public class TestStorage : MongoStorageObject
	{
	}
}

Then, in a Microservice, the TestDocument can be created, read, updated, and deleted as shown below.

using Beamable.Mongo;
using Beamable.Server;
using MongoDB.Driver;
using System.Collections.Generic;

namespace Beamable.Microservices
{
	[Microservice("TestMicroservice")]
	public class TestMicroservice : Microservice
	{
		[ClientCallable]
		public async void Get(string id)
		{
			TestDocument document = await Storage.Get<TestStorage, TestDocument>(id);
		}

		[ClientCallable]
		public async void Create(int intValue, string stringValue)
		{
			await Storage.Create<TestStorage, TestDocument>(new TestDocument
			{
				IntValue = intValue, StringValue = stringValue,
			});
		}

		[ClientCallable]
		public async void Update(string id, int intValue, string stringValue)
		{
			await Storage.Update<TestStorage, TestDocument>(id, new TestDocument
			{
				IntValue = intValue,
				StringValue = stringValue
			});
		}

		[ClientCallable]
		public async void Delete(string id)
		{
			await Storage.Delete<TestStorage, TestDocument>(id);
		}
	}
}
📘

The Collection Name is the Class Name

When you use these helper methods, the Mongo Collection for the TestDocument class will be called "TestDocument".