Azure

State Administration in Azure Service Cloth

Introduction

This text makes use of code from my earlier article Implementing Actor Mannequin in Azure Service Cloth

Street Map

  • Creating Checkout Service
  • Testing Utilizing Postman
  • Use Instances

Creating Checkout service

Within the final module, we constructed a consumer actor service on prime of the actor framework, making consumer baskets extraordinarily scalable. There’s one final piece left to do, checkout service. Checkout service, identical to the product catalog, is a stateful service. Its objective is to make the consumer basket carry out the checkout course of. This merely means taking inventory from the product catalog service, producing the receipt, and clearing the basket.

Step 1. Create a brand new service cloth Stateful service named CheckoutService.

Fabric service

Step 2. Now create a brand new .Web commonplace library challenge and identify it Ecommerce.CheckoutService.Mannequin.

Library project

Step 3. Create an interface named ICheckoutService on this challenge.

public interface ICheckoutService : IService {
}

Step 4. Set up the lacking package deal.

Step 5. Create a brand new class, CheckoutSummary, on the identical challenge.

public class CheckoutSummary {
    public Checklist<CheckoutProduct> Merchandise { get; set; }
    public double TotalPrice { get; set; }
    public DateTime Date { get; set; }
}

CheckoutSummary will maintain the results of the checkout course of and can embrace the entire value of all of the merchandise we try, the date of the checkout, and the checklist of checkout merchandise. The CheckoutProduct class shouldn’t be outlined but. I will add it right here as a easy class.

Step 6. Create a brand new class CheckoutProduct in the identical Mannequin challenge as proven.

public class CheckoutProduct {
    public Product Product { get; set; }
    public int Amount { get; set; }
    public double Worth { get; set; }
}

The CheckoutProduct accommodates a couple of fields: amount of the variety of merchandise purchased, a value we paid for this buy, and a reference to the unique product. Now, this unique product is contained throughout the ProductCatalog service we have created earlier than; due to this fact, add a reference to this challenge from the checkout service mannequin product. So now we’re all good.

Now I’ll outline two operations for our checkout service. This ought to be an interface, in fact. One in all them is named checkout, which, given a consumer ID, will return us a checkout abstract. And the opposite one will return the order historical past for this consumer within the type of a set of checkout summaries.

Step 7. Add the next code to the ICheckoutService interface.

public interface ICheckoutService : IService {
    Job<CheckoutSummary> CheckoutAsync(string userId);
    Job<CheckoutSummary[]> GetOrderHistoryAsync(string userId);
}

Step 8. Now go to the e-commerce.API challenge and create a brand new controller CheckoutController. Add the next code.

non-public static readonly Random rnd = new Random(DateTime.UtcNow.Second);

[Route("{userId}")]
public async Job<ApiCheckoutSummary> CheckoutSummary(string userId)
{
    CheckoutSummary abstract = await GetCheckoutService().CheckoutAsync(userId);
    return ToApiCheckoutSummary(abstract);
}

[Route("history/{userId}")]
public async Job<IEnumerable<ApiCheckoutSummary>> GetHistoryAsync(string userId)
{
    IEnumerable<CheckoutSummary> historical past = await GetCheckoutService().GetOrderHistoryAsync(userId);
    return historical past.Choose(ToApiCheckoutSummary);
}

Step 9. Add the 2 courses ApiCheckoutProduct and ApiCheckoutSummaryto the mannequin folder of Ecommerce.API challenge.

public class ApiCheckoutProduct {
    [JsonProperty("productId")]
    public Guid ProductId { get; set; }
    [JsonProperty("productname")]
    public string ProductName { get; set; }
    [JsonProperty("quantity")]
    public int Amount { get; set; }
    [JsonProperty("price")]
    public double Worth { get; set; }
}
public class ApiCheckoutSummary {
    [JsonProperty("products")]
    public Checklist<ApiCheckoutproduct> Merchandise { get; set; }
    [JsonProperty("date")]
    public DateTime Date { get; set; }
    [JsonProperty("totalprice")]
    public double TotalPrice { get; set; }
}

ApiCheckoutProduct merely accommodates the product ID, product identify, amount, and value. That is similar to the checkout product entity in our different mannequin challenge. Moreover, ApiCheckoutSummary accommodates the checklist of merchandise, the entire value, and the date of the checkout. On this controller, now we have simply two strategies. The primary one is checkout, which merely forwards the decision to the checkout service, calls the an identical checkout methodology, and converts it to the ApiCheckoutSummary. As you possibly can see, it is a easy conversion between two courses. The second is GetHistory, which additionally forwards calls to the GetOrderHistory methodology on the checkout service class and, once more, converts it to the ApiCheckoutSummary.

Step 10. Add the next three capabilities to CheckoutController.

non-public ApiCheckoutSummary ToApiCheckoutSummary(CheckoutSummary mannequin) {
    return new ApiCheckoutSummary {
        Merchandise = mannequin.Merchandise.Choose(p => new ApiCheckoutProduct {
            ProductId = p.ProductId,
            ProductName = p.ProductName,
            Worth = p.Worth,
            Amount = p.Amount
        }).ToList(),
        Date = mannequin.Date,
        TotalPrice = mannequin.TotalPrice
    };
}

non-public ICheckoutService GetCheckoutService() {
    lengthy key = LongRandom();
    var proxyFactory = new ServiceProxyFactory(c => new FabricTransportServiceRemotingClientFactory());
    return proxyFactory.CreateServiceProxy<ICheckoutService>(new Uri("cloth:/Ecommerce/Ecommerce.ProductCatalog"), new ServicePartitionKey(key));
}
non-public lengthy LongRandom() {
    byte[] buf = new byte[8];
    rnd.NextBytes(buf);
    lengthy longRand = BitConverter.ToInt64(buf, 0);
    return longRand;
}

Now, let’s implement the checkout service. We have already achieved it earlier than with different providers, however I will velocity by it once more. To begin with, I will delete the RunAsync methodology since we merely do not want it, take away the pointless feedback, and as you keep in mind, with a view to expose an endpoint, we have to substitute CreateServiceReplicaListener with this an identical code we have written earlier than. In fact, to ensure that that to work, it is advisable both reference the Microsoft.ServiceFabric.Companies.Remoting Library.

protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListener() {
    return new[]{
        new ServiceReplicaListener(context => new FabricTransportServiceRemotingListener(context, this))
    };
}

Step 11. Derive the CheckoutService Class from the ICheckoutService. In fact, Visual Studio does not learn about it, so we have to add a reference to the mannequin challenge.

And now let’s merely implement this interface. We have two strategies, Checkout and GetOrderHistory, which aren’t carried out but. Let’s implement them and clarify the way it works.

First, we are going to create the CheckoutSummary class occasion which holds the outcomes of the checkout, units the date, and initializes the product with an empty assortment. Earlier than we try, we have to get the consumer basket. Due to this fact, we should get a reference to the IUserActor.

To get the consumer actor, I wrote a helper methodology, GetUserActor, which merely creates an actor proxy, calling the UserActor service. Then we want the IProductCatalog service. That is contained inside ECommerce.Product catalog.Mannequin Challenge and once more, I used to be in a position to write a trivial helper methodology for this. It merely creates a service proxy for the product catalog service.

Now that now we have each consumer basket and catalog service, what we wish to do with a view to proceed to the checkout is to enumerate by the basket. For every basket line, get a product from the basket, create the CheckoutProduct entity, and fill in all of the required fields (i.e. product, value, amount, calculate the entire value, clear the basket, and add this buy to the historical past). So as to add the product to the historical past, I wrote one other helper methodology. All it does is create an occasion of a dependable assortment known as historical past, open a transaction, and add the CheckoutSummary to that historical past. That may assist us later retrieve the consumer’s buying historical past by the identical API.

Step 12. Implement the CheckoutAsync methodology as follows.

public async Job<CheckoutSummary> CheckoutAsync(string userId)
{
    var consequence = new CheckoutSummary();
    consequence.Date = DateTime.UtcNow;
    consequence.Merchandise = new Checklist<CheckoutProduct>();
    IUserActor userActor = GetUserActor(userId);
    BasketItem[] basket = await userActor.GetBasket();
    IProductCatalogService catalogService = GetProductCatalogService();
    foreach (BasketItem basketLine in basket)
    {
        Product product = await catalogService.GetProductAsync(basketLine.ProductId);
        var checkoutProduct = new CheckoutProduct
        {
            Product = product,
            Worth = product.Worth,
            Amount = basketLine.Amount
        };
        consequence.Merchandise.Add(checkoutProduct);
    }
    consequence.TotalPrice = consequence.Merchandise.Sum(p => p.Worth);
    await userActor.ClearBasket();
    await AddToHistoryAsync(consequence);
    return consequence;
}

Step 13. Add the next helper strategies.

non-public IUserActor GetUserActor(string userId)
{
    return ActorProxy.Create<IUserActor>(new ActorId(userId), new Uri("cloth:/Ecommerce/UserActorService"));
}
non-public IProductCatalogService GetProductCatalogService()
{
    var proxyFactory = new ServiceProxyFactory(c => new FabricTransportServiceRemotingClientFactory());
    return proxyFactory.CreateServiceProxy<IProductCatalogService>(new Uri("cloth:/Ecommerce/Ecommerce.ProductCatalog"), new ServicePartitionKey(0));
}
non-public async Job AddToHistoryAsync(CheckoutSummary checkout) {
    IReliableDictionary<DateTime, CheckoutSummary> historical past = await StateManager.GetOrAddAsync<IReliableDictionary<DateTime, CheckoutSummary>>("historical past");
    utilizing (ITransaction tx = StateManager.CreateTransaction()) {
        await historical past.AddAsync(tx, checkout.Date, checkout);
        await tx.CommitAsync();
    }
}

Now, implementing order historical past is straightforward contemplating we have already written the historical past merchandise for the historical past assortment. In fact, this methodology needs to be async. We get the reference to the historical past assortment, create a transaction, merely enumerate by the entire objects within the historical past assortment, and return it as a listing of checkout summaries.

Step 14. Implement GetOrderHistoryAsync as follows.

public async Job<CheckoutSummary[]> GetOrderHistoryAsync(string userId)
{
    var consequence = new Checklist<CheckoutSummary>();
    IReliableDictionary<DateTime, CheckoutSummary> historical past = await StateManager.GetOrAddAsync<IReliableDictionary<DateTime, CheckoutSummary>>("historical past");
    utilizing (ITransaction tx = StateManager.CreateTransaction())
    {
        IAsyncEnumerable<KeyValuePair<DateTime, CheckoutSummary>> allProducts = await historical past.CreateEnumerableAsync(tx, EnumerableMode.Unordered);
        utilizing (IAsyncEnumerator<KeyValuePair<DateTime, CheckoutSummary>> enumerator = allProducts.GetAsyncEnumerator())
        {
            whereas (await enumerator.MoveNextAsync(CancellationToken.None))
            {
                KeyValuePair<DateTime, CheckoutSummary> present = enumerator.Present;
                consequence.Add(present.Worth);
            }
        }
    }
    return consequence.ToArray();
}

Check Utilizing Postman

We will check it by launching our software, and once more utilizing this excellent Postman software. We’ll begin by calling the product’s API to get the product checklist from the product catalog.

 API

Let’s add a product to the consumer’s basket by calling the Put up methodology.

Post method

Now, we carry out a checkout for consumer 1. And as you possibly can see, now we have the checkout abstract. Moreover, we nonetheless have the worth, date, and checklist of merchandise. All appears to be appropriate, so that is achieved. That’s how we handle the state in service cloth.

Send

Relevant Instances

  • Keep away from advanced techniques involving dependencies and coordinating shared state
  • Once you need to keep away from utilizing express locks to guard the shared state
  • Traditional synchronization issues just like the eating thinker’s and the sleeping barber’s drawback
  • Extremely out there providers
  • Scalable providers

Abstract

On this article, we realized about managing state in Azure Service Cloth.

Know extra about our firm at Skrots. Know extra about our providers at Skrots Companies, Additionally checkout all different blogs at Weblog at Skrots

Show More

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button