Skip to content

Instantly share code, notes, and snippets.

@enricosoft
Created May 2, 2023 17:14
Show Gist options
  • Save enricosoft/c2507c056617b94ab4e60c9b54528ebd to your computer and use it in GitHub Desktop.
Save enricosoft/c2507c056617b94ab4e60c9b54528ebd to your computer and use it in GitHub Desktop.
Microsoft Orleans.NET Sample
1) [ORLEANS.NET BACK-END]
// GRAIN (ACTOR) INTERFACE DEFINITION (ICartGrain.cs)
namespace GrainInterfaces
{
public interface ICartGrain : IGrainWithGuidKey
{
Task<Cart> GetCart();
Task<List<Product>> GetProducts();
Task AddProduct(Product product);
}
}
// GRAIN (ACTOR) IMPLEMENTATION (CartGrain.cs)
namespace Grains
{
[StorageProvider(ProviderName="CartStorage")]
public class CartGrain : Grain<CartState>, ICartGrain
{
public async Task<Cart> GetCart()
{
await ReadStateAsync();
if (State.Value != null) return State.Value;
State.Value = new Cart
{
Id = Guid.NewGuid(),
Products = new List<Product>()
};
await WriteStateAsync();
return State.Value;
}
public async Task<List<Product>> GetProducts()
{
await ReadStateAsync();
return State.Value.Products;
}
public async Task AddProduct(Product product)
{
await ReadStateAsync();
if (State.Value == null)
{
State = new CartState();
}
State.Value.Products.Add(product);
await WriteStateAsync();
}
}
}
// SILO IMPLEMENTATION (Program.cs)
namespace Silo
{
public class Program
{
static async Task Main(string[] args)
{
var siloBuilder = new SiloHostBuilder()
.UseLocalhostClustering(serviceId:"blog-orleans-deepdive")
.AddAdoNetGrainStorage("CartStorage", options=>
{
options.Invariant = "System.Data.SqlClient";
options.ConnectionString = "Data Source=localhost,1433;Initial Catalog=ServicePersistence;Integrated Security=False;User ID=sa;Password=xxxxx";
options.UseJsonFormat = true;
})
.ConfigureLogging(logging => logging.AddConsole())
.UseDashboard();
using (var host = siloBuilder.Build())
{
await host.StartAsync();
Console.ReadLine();
}
}
}
}
2) [CART FRONT-END]
// CART API CONFIGURATION (Startup.cs)
namespace Cart.API
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton(CreateClusterClient);
}
private IClusterClient CreateClusterClient(IServiceProvider serviceProvider)
{
var client = new ClientBuilder()
.UseLocalhostClustering( serviceId: "blog-orleans-deepdive")
.ConfigureApplicationParts(parts => parts.AddApplicationPart(typeof(ICartGrain).Assembly).WithReferences())
.ConfigureLogging(_ => _.AddConsole())
.Build();
StartClientWithRetries( client).Wait();
return client;
}
public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
app.UseDefaultFiles();
app.UseStaticFiles();
}
private static async Task StartClientWithRetries(IClusterClient client)
{
for (var i = 0; i < 5; i++)
{
try
{
await client.Connect();
return;
}
catch (Exception)
{
// ignored
}
await Task.Delay(TimeSpan.FromSeconds(5));
}
}
}
}
// CART API IMPLEMENTATION USING ORLEANS .NET CLIENT (CartController)
namespace Cart.API.Controllers
{
[Route("api/cart")]
public class CartController : Controller
{
private readonly IClusterClient _client;
public CartController(IClusterClient client)
{
_client = client;
}
[HttpGet("{id}")]
public async Task<GrainInterfaces.States.Cart> Get(Guid id)
{
var grain = _client.GetGrain<ICartGrain>(id);
return await grain.GetCart();
}
[HttpGet("{id}/product")]
public async Task<List<Product>> GetProduct(Guid id)
{
var grain = _client.GetGrain<ICartGrain>(id);
return await grain.GetProducts();
}
[HttpPost("{id}/product")]
public async Task AddProduct(Guid id, [FromBody]Product product)
{
var grain = _client.GetGrain<ICartGrain>(id);
await grain.AddProduct(product);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment