Created
May 2, 2023 17:14
-
-
Save enricosoft/c2507c056617b94ab4e60c9b54528ebd to your computer and use it in GitHub Desktop.
Microsoft Orleans.NET Sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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