Newbe.Claptrap框架入门,第四步——使用Minion
接上一篇 ,我们继续要了解一下如何使用 Newbe.Claptrap 框架开发业务。通过本篇阅读,您便可以开始学会在 Claptrap 框架中使用 Minion 进行异步的业务处理。
该开发文档已经过期
该开发文档仅适用于 Newbe.Claptrap 0.7 及以下版本。若要查看最新的开发文档,请移步 https://claptrap.newbe.pro
开篇摘要
本篇,我通过实现“商品下单”的需求来了解一下如何在已有的项目样例中使用 Minion 来完成异步的业务处理。
首先,先了解一下本篇需要涉及的业务用例:
- 用户可以进行下单操作,下单时将使用当前购物车中的所有 SKU 形成一个订单。
- 下单后将会扣除相关 SKU 的库存。如果某一 SKU 库存不足,则下单失败。
- 下单操作仅到扣减库存成功为止,后续步骤不需要本样例讨论范围。因此,本样例在成功下单之后会在数据库中生成一条订单记录,表示订单创建结束。
本篇虽然重点在于 Minion 的使用,不过由于需要使用到一个新的 OrderGrain 对象,因此还是需要使用到前一篇“定义 Claptrap”的相关知识。
Minion 是一种特殊的 Claptrap,它与其 MasterClaptrap 之间的关系如下图所示:
其主体开发流程和 Claptrap 类似,只是有所删减。对比如下:
步骤 | Claptrap | Minion |
---|---|---|
定义 ClaptrapTypeCode | √ | √ |
定义 State | √ | √ |
定义 Grain 接口 | √ | √ |
实现 Grain | √ | √ |
注册 Grain | √ | √ |
定义 EventCode | √ | |
定义 Event | √ | |
实现 EventHandler | √ | √ |
注册 EventHandler | √ | √ |
实现 IInitialStateDataFactory | √ | √ |
这个删减的原因是由于 Minion 是 Claptrap 的事件消费者,所以事件相关的定义不需要处理。但是其他的部分仍然是必须的。
本篇开始,我们将不再罗列相关代码所在的具体文件位置,希望读者能够自行在项目中进行查找,以便熟练的掌握。
实现 OrderGrain
基于前一篇“定义 Claptrap”相关的知识,我们此处实现一个 OrderGrain 用来表示订单下单操作。为节约篇幅,我们只罗列其中关键的部分。
OrderState
订单状态的定义 如下:
using System.Collections.Generic;
using Newbe.Claptrap;
namespace HelloClaptrap.Models.Order
{
public class OrderState : IStateData
{
public bool OrderCreated { get; set; }
public string UserId { get; set; }
public Dictionary<string, int> Skus { get; set; }
}
}
- OrderCreated 表示订单是否已经创建,避免重复创建订单
- UserId 下单用户 Id
- Skus 订单包含的 SkuId 和订单量
OrderCreatedEvent
订单创建事件的定义如下:
using System.Collections.Generic;
using Newbe.Claptrap;
namespace HelloClaptrap.Models.Order.Events
{
public class OrderCreatedEvent : IEventData
{
public string UserId { get; set; }
public Dictionary<string, int> Skus { get; set; }
}
}
OrderGrain
using System.Threading.Tasks;
using HelloClaptrap.Actors.Order.Events;
using HelloClaptrap.IActor;
using HelloClaptrap.Models;
using HelloClaptrap.Models.Order;
using HelloClaptrap.Models.Order.Events;
using Newbe.Claptrap;
using Newbe.Claptrap.Orleans;
using Orleans;
namespace HelloClaptrap.Actors.Order
{
[ClaptrapEventHandler(typeof(OrderCreatedEventHandler), ClaptrapCodes.OrderCreated)]
public class OrderGrain : ClaptrapBoxGrain<OrderState>, IOrderGrain
{
private readonly IGrainFactory _grainFactory;
public OrderGrain(IClaptrapGrainCommonService claptrapGrainCommonService,
IGrainFactory grainFactory)
: base(claptrapGrainCommonService)
{
_grainFactory = grainFactory;
}
public async Task CreateOrderAsync(CreateOrderInput input)
{
var orderId = Claptrap.State.Identity.Id;
// throw exception if order already created
if (StateData.OrderCreated)
{
throw new BizException($"order with order id already created : {orderId}");
}
// get items from cart
var cartGrain = _grainFactory.GetGrain<ICartGrain>(input.CartId);
var items = await cartGrain.GetItemsAsync();
// update inventory for each sku
foreach (var (skuId, count) in items)
{
var skuGrain = _grainFactory.GetGrain<ISkuGrain>(skuId);
await skuGrain.UpdateInventoryAsync(-count);
}
// remove all items from cart
await cartGrain.RemoveAllItemsAsync();
// create a order
var evt = this.CreateEvent(new OrderCreatedEvent
{
UserId = input.UserId,
Skus = items
});
await Claptrap.HandleEventAsync(evt);
}
}
}
- OrderGrain 实现订单的创建核心逻辑,其中的 CreateOrderAsync 方法完成购物车数据获取,库存扣减相关的动作。
- OrderCreatedEvent 执行成功后将会更新 State 中相关的字段,此处就不在列出了。