Skip to content

Latest commit

 

History

History
139 lines (93 loc) · 10.6 KB

emall-1-order-generate.md

File metadata and controls

139 lines (93 loc) · 10.6 KB

接收订单

我们假设已经有了一个商城系统,用户在这个系统里可以选购商品并提交订单。现在我们要借助 Nature 来接管订单的后续处理过程。

Q:是否可以将选购商品等这些商城的职能用 Nature 来实现?

A:Nature 目前倾向于后端处理,没有前端交互能力,但可以为前端提供数据,即使是提供数据,现在功能上还不完备,如支持缓存等。

外系统提交订单

我们需要用 json 格式来提交订单数据,并将数据提交到http://localhost:8080/input。如果成功该接口则会返回一个instance实例的ID。提交的具体方式请参考

nature-demo::emall::emall_test()

json 格式示例如下:

{"data":{"meta":"B:sale/order:1","content":"please fill this property with real order data..."}}
  • data.meta=“B:sale/order:1”:说明这是一个订单数据,Meta 必须事先在 Nature 中注册才能使用,下面会讲怎么注册。
  • data.content="..."则是订单的实际内容。

在Nature里注册Meta:订单

要想让Nature 接受 上面的订单信息输入,我们需要向 meta 数据表里插入下面的数据:

INSERT INTO meta
(meta_type, meta_key, description, version, states, fields, config)
VALUES('B', 'sale/order', 'order', 1, '', '', '');

:本demo中所用的sql 都可以再 demo-emall.sql 中找到,其它 demo 也都有对应的 sql 文件。

我们逐一解释一下:

  • meta_type='B': 为Meta指定类型B,B指的是MetaType::Business,代表这是一个业务对象,其他类型可参考meta.md
  • meta_key='sale/order' : 为Meta的名字,用于区别其它业务对象的定义。
  • description=‘order’:向别人介绍一下这个Meta是干什么的,意义是什么等。
  • version=1: 当前业务对象定义的版本号。
  • Nature 要点:每当业务定义发生变更时,可以插入更高版本的业务定义,而不是更新原有的业务定义。这种做法的好处是可以使业务平滑过渡,而不用担心上一版本正在处理中的数据受到影响,Nature 为业务系统的迭代提供了良好的内在支持

查看输入的数据

让我们先看看 Nature 所插入数据的样子。运行:

nature.exe
cargo.exe test --color=always --package nature-demo --lib emall::emall_test

打开 instance 数据表,我们会发现有下面的数据:

ins_key content
B:sale/order:1|3827f37003127855b32ea022daa04cd| {"user_id":123,"price":1000,"items":[{"item":{"id":1,"name":"phone","price":800},"num":1},{"item":{"id":2,"name":"battery","price":100},"num":2}],"address":"a.b.c"}
  • “B:sale/order:1” 实际上就是**”meta_type:meta_key:version“**的值的表现形式,Nature 称之为 meta_string
  • ins_key:用于唯一标记此条数据。其构成为 “meta_string|id|para”。此例中我们没有输入id,Nature会用输入数据的 hash 值来作为此条数据的 ID,这样做的目的是为了追求幂等。此例中我们也没有输入 para ,所以此条数据尾巴上只有一个“|”
  • Nature 要点:之所以不省去看似“无意义”的“|”是为了便于进行 like 数据检索时有一个明确的休止符。
  • content 是我们模拟的订单数据,这个数据是 emall_test() 给出的,大家可以自行去看源码。

定义订单状态

先结束 nature.exe 的运行,我们继续完善我们的示例。

这个示例的要点就是要跟踪订单的处理状态。状态数据是不建议直接放到B:sale/order:1上的。

  • Nature 要点:Nature 会为每次状态变更单独记录一个版本,如果订单状态与订单合并,就会有很多的冗余,性能也好不到那里去。所以Nature 是非常提倡将基本信息和状态信息分成两个 Meta 这种做法的。
  • Nature 要点:独立的状态数据会更有利于流程梳理,可以使我们非常直观的、严格的将数据分成有状态的和无状态的,而不是一个混合体从而导致业务概念混乱不清。

为此我们需要为订单状态单独创建一个Meta:

INSERT INTO meta
(meta_type, meta_key, description, version, states, fields, config)
VALUES('B', 'sale/orderState', 'order state', 1, 'new|paid|package|outbound|dispatching|signed|canceling|canceled', '', '{"master":"B:sale/order:1"}');
  • states='new|paid|package|outbound|dispatching|signed|canceling|canceled': 这里定义了我们订单里要用的的状态。“|”说明这些状态不能共存,同一时间里只能是其中的一个。具体语法请参考:使用meta
  • master="B:sale/order:1":说明 orderState 依附于订单。其作用有两个:
    • orderState 会使用 订单的ID作为自己的ID
    • orderState 作为上游驱动下游数据时,Nature 会顺便将 order 数据传递给下游,这样下游就不需要单独再查询一次订单数据了。

定义订单订单状态之间的关系

要想生成订单状态数据,我们需要建立起订单和订单状态之间的关系。请执行下面的sql:

INSERT INTO relation
(from_meta, to_meta, settings)
VALUES('B:sale/order:1', 'B:sale/orderState:1', '{"target":{"state_add":["new"]}}');
字段或属性 说明
from_meta 关系的起点,为 meta_string
to_meta 关系的终点,为 meta_string
settings 是一个 JSON 形式的配置对象,用于对这个关系进行一些附加控制,如执行器过滤器以及对上下游实例的一些要求等。请参考使用 Relation
  • Nature 要点:在Nature 关系是有方向的,这个方向说明了数据的流转方向,上面的关系定义说明了数据只能从 B:sale/order:1 流向 B:sale/orderState:1。
  • target.state_add=["new"]:是说在新生成的数据实例(B:sale/orderState:1)上附加上”new“ 状态。这个语法是数组,也就是说我们可以同时附加多个状态。
  • Nature 要点:这个附加是在上一个版本的状态基础上进行附加的。对于本例来讲上一版本还不存在,则认为上一状态为“[]”。

运行 Demo 并查看生成的订单状态数据

让我们见证一个魔法时刻,运行:

nature.exe
cargo.exe test --color=always --package nature-demo --lib emall::emall_test

打开 instance 数据表,我们会发现有一条下面的数据:

ins_key states state_version from_key
B:sale/orderState:1|3827f37003127855b32ea022daa04cd| ["new"] 1 B:sale/order:1|3827f37003127855b32ea022daa04cd|

我们只 在metarelation数据表里加了两条配置数据,神奇的是instance数据表里自动生成了一条“sale/orderState”数据。

  • Nature 要点:当关系中的下游Instance.content没有意义时,我们就不需要一个明确的执行器来完成关系所要求的数据转换任务,在此种情况下Nature 会为关系自动生成一个类型为auto执行器,正是这个执行器帮助我们生成了上面这条数据。 有关使用执行器的例子,在后续的章节中会讲到。
  • Nature 要点:传统编程方式下,对状态数据进行编码是一项无法避免的工作,但 Nature 可以替你完成这件工作,使程序员把精力放到真正需要的地方。
  • Nature 要点:将订单数据和状态数据分开存储,相较于传统方式的合并存储,看似复杂化了设计,但对 Nature 来讲这却是规范性的设计,这种规范性有利于 Nature 为你简化代码实现的复杂度,如本例所看到的,Nature 可以为你自动生成状态数据并操作状态;如果是合在一起,那么有些事情就需要程序员自己来处理了。

如果仔细看,你会发现上面这条数据的ins_keyfrom_key 中的 ID 是相同的,这是Meta.master设置在起作用。

  • Nature 要点:master 属性既规范了业务描述又简化了开发。
  • Nature 要点 :在 Nature 里多个不同元数据实例共享相同的 ID 是一种推荐的做法,这个ID 可以被视为一个事务ID。这样用一个ID就可以把所有相关的数据提取出来。这要比依赖于外键的传统数据表提取数据有效率的多,而且还减少了关系数据的维护。更重要的是这种处理方式减少了保障数据一致性的技术复杂度
  • Nature 要点from_key 是 Nature 自动添加的,可用于追溯数据,这会为排查问题提供极大的方便。

同时我们发现target.state_add=["new"]也发挥了作用:这条数据的states被设置成["new"]了。

  • Nature 要点:对于状态处理我认为是传统编程方式下最复杂、最容易出错和最难维护的部分之一,而 Nature 为此提供了一整套处理机制,程序员基本上无需干预就可以处理好所有状态相关的问题,这在后续demo中会经常得到体现。

在本示例的源码中,我们多次提交了相同的订单数据,Nature 会返回相同的ID,也就是说 Nature 是幂等的

  • Nature 要点:幂等是 Nature 设计的一个重要原则,是保障数据一致性以及失败任务可以重试的重要机制。