Skip to content

Latest commit

 

History

History
104 lines (66 loc) · 7.01 KB

emall-4-stock-out.md

File metadata and controls

104 lines (66 loc) · 7.01 KB

出库

现在我们该履行合同了。第一步就是出库,我们假设库房管理系统已经存在,为此我们需要实现一个执行器来与库房系统通讯。但因为库房的拣货、打包涉及到人工和(或)机械设备的处理,时间很长,导致执行器执行超时,无法与Nature 协作,既同步的方式无法满足 Nature 的通讯要求。

一些限制说明

在真实的情况中,一个订单可能包含不同的商品,而这些商品也可能分布在不同的库房中。本示例为了简单起见,假定所有的商品都在同一个库房里。

这里有两种解决方法,第一种方式是建立如下关系, 用执行器将 Nature 的订单加工成出库单并导入到库房系统。

-- orderState:paid --> stockOutApplication
INSERT INTO relation
(from_meta, to_meta, settings)
VALUES('B:sale/orderState:1', 'N:warehouse/outApplication:1', '{"selector":{"state_all":["paid"]},"executor":{"protocol":"localRust","url":"nature_demo:stock_out_application"}}');
  • Nature 要点:请注意这里的N:warehouse/outApplication:1,我们之前并没有定义过,这是一个不存在的Meta。 为了简化配置工作,对于没有存储意义的Meta不需要定义就可以使用,出库单是存储到库房系统里的,没有必要再在 Nature 里存储一份。我们用N:来标记这样的Meta,N 代表 MetaType::Nullwarehouse/outApplication只是助记符,N:warehouse/outApplication:1 完全可以写成N::1,后面的版本号无论是多少都会被置为1,因为“空”有很多版本也没有意义。请参考 meta.md
  • Nature 要点:Nature 并不会因为不保存 MetaType::Null 类型的实例数据,而降低服务质量,同样的保障机制会作用在相关的执行器上。

出库单进入库房系统后,人员及设备就可以开工了,当打包完成后就需要调用 Nature 的 input 接口来改变订单的状态,以驱动订单后面的流程。但这种方式,少了一些规范性和约束性,因为库房系统必须填写下面的信息如下:

  • 目标Meta为:B:sale/orderState:1
  • instance的状态置为 package
  • 设置状态的版本号

会有下面的问题:

  • 这些信息必须通过编程的方式提交,这样程序员就必须要了解订单状态相关的知识,扩大了信息沟通和维护成本。
  • 程序员可能会指定不规范的状态版本号,还有就是必须编程应对状态版本冲突的问题。

其实这两个问题都可以避免,这就是我们的第二中方法,也是本示例所采用的方法:利用 Nature 的回调机制

订单状态:支付->打包完成

当我们支付完成后,订单状态就会停在paid上,直到库房系统给出一个新的状态,所以我们可以定义一个订单状态到订单状态的关系

-- orderState:paid --> orderState:package
INSERT INTO relation
(from_meta, to_meta, settings)
VALUES('B:sale/orderState:1', 'B:sale/orderState:1', '{"selector":{"state_all":["paid"]},"executor":{"protocol":"http","url":"http://localhost:8082/send_to_warehouse"},"target":{"state_add":["package"]}}');
  • Nature 要点:我们这里看到了一种新的执行器:http,借助它 Nature 可以在全球范围内编织一个庞大的系统。

  • Nature 要点:nature_demo_executor_restful 项目已经提供了对上面url的支持,实现逻辑大家可自行下载源码进行查看。

send_to_warehouse 的实现方式是这样的,将入参直接传递给一个新的线程(实际生产中,你可以采用更好的处理方式)来处理,自己什么也不做并直接返回 下面的结果给 Nature:

ConverterReturned::Delay(60)

这个的意思是说,我要晚会给你(Nature)结果,多晚呢?60秒内。

  • Nature 要点:Nature 在 Delay 指定的时间内不会进行重试。如果不指定 Delay Nature 在没有得到响应的情况下,会在接下来的第2、4、8、16、32、64...秒(依据启动参数来确定)进行重试,直到有反馈为止。
  • Nature 要点:这里的延迟时间是个技术问题,不是业务问题,所以就不放到关系里面进行配置了,如果放到那里反而不灵活了。

因为这是个Demo,我们只在50ms便返回了结果。当返回结果时我们不能调用 Nature 的 input 接口了,否则 Nature 挂起的任务会在将来的某个时刻重试。这里应当调用 Nature 的 callback 接口,它接受 DelayedInstances类型的示例。请注意别忘了把执行器得到的 task_id 给带上,具体请看示例代码。

让我们来看下效果,运行:

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

结束后我们会发现有下面的数据产生:

ins_key states state_version from_key
B:sale/orderState:1|3827f37003127855b32ea022daa04cd| ["package"] 3 B:sale/orderState:1|3827f37003127855b32ea022daa04cd||2

订单状态:出库

打包对库房来说只是个中间状态,只是为了让顾客及时了解到货物的状态。我们还需要把货物放到出库区,让配送人员将货物拉走。这个出库状态也可以走 Nature 回调的路子,实现状态的配置化,但为了演示如何向 Nature 提交状态数据,这里放弃了这种做法,而是直接将状态数据提交到 Nature 的 input 接口,具体请看示例代码。

  • Nature 要点:一定要设置instance.id 为要订单的ID,否则Nature 会分配一个新的ID,这将导致订单在系统中无法出库。
  • Nature 要点state_version 必须要在原有的基础上加一,否则会引起冲突,无法处理。

让我们来看下效果,运行:

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

结束后我们会发现有下面的数据产生:

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

请留意这里的 from_key 为空,这是因为这条数据是外部输入时没有指定这个值,对于这种情况 Nature 不能自动填充这个值。

多个库房

这里并不是刻意想着构建一个庞大的电商系统(当然 Nature 有这个能力),只是因为借助多库房来演示 Nature 的一种新技术:上下文选择。如想立马了解可以点击链接:附录-多个库房