Wow是基于DDD、EvetSourcig的现代响应式CQRS架构微服务开发框架。
领域驱动 | 事件驱动 | 测试驱动 | 声明式设计 | 响应式编程 | 命令查询职责分离 | 事件源架构图事件源可观测性SprigWebFlux集成自动注册 命令 路由处理函数(HadlerFuctio),开发人员仅需编写领域模型,即可完成服务开发。测试套件:80%+的测试覆盖率轻而易举Give->Whe->Expect.前置条件理解 领域驱动设计:《实现领域驱动设计》、《领域驱动设计:软件核心复杂性应对之道》理解 命令查询职责分离(CQRS)理解 事件源架构理解 响应式编程特性 AggregateModelig SigleClass IheritacePatter AggregatioPatter SagaModelig StatelessSaga TestSuite 兼容性测试规范(TCK) AggregateVerifier SagaVerifier EvetSourcigEvetStore MogoDB(Recommed) R2dbc DatabaseShardig TableShardig RedisSapshot MogoDB R2dbc DatabaseShardig TableShardig ElasticSearch Redis(Recommed) CommadBus IMemoryCommadBus KafkaCommadBus (Recommed) RedisCommadBus LocalFirstCommadBus DomaiEvetBus IMemoryDomaiEvetBus KafkaDomaiEvetBus (Recommed) RedisDomaiEvetBus LocalFirstDomaiEvetBus StateEvetBus IMemoryStateEvetBus KafkaStateEvetBus (Recommed) RedisStateEvetBus LocalFirstStateEvetBus Sprig集成 SprigBootAutoCofiguratio Automaticallyregister CommadAggregate to RouterFuctio 可观测性 OpeTelemetry OpeApi WowMetadata Geerator wow-compilerExampleExample测试套件80%+的测试覆盖率轻而易举。Give->Whe->Expect.iteralclassOrderTest{compaioobject{valSHIPPING_ADDRESS=ShippigAddress("Chia","ShagHai","ShagHai","HuagPu","001")}privatefumockCreateOrder():VerifiedStage<OrderState>{valteatId=GlobalIdGeerator.geerateAsStrig()valcustomerId=GlobalIdGeerator.geerateAsStrig()valorderItem=OrderItem(GlobalIdGeerator.geerateAsStrig(),GlobalIdGeerator.geerateAsStrig(),BigDecimal.valueOf(10),10)valorderItems=listOf(orderItem)valivetoryService=object:IvetoryService{overridefugetIvetory(productId:Strig):Moo<It>{returorderItems.toFlux().filter{it.productId==productId}.map{it.quatity}.last()}}valpricigService=object:PricigService{overridefugetProductPrice(productId:Strig):Moo<BigDecimal>{returorderItems.toFlux().filter{it.productId==productId}.map{it.price}.last()}}returaggregateVerifier<Order,OrderState>(teatId=teatId).iject(DefaultCreateOrderSpec(ivetoryService,pricigService)).give().`whe`(CreateOrder(customerId,orderItems,SHIPPING_ADDRESS)).expectEvetCout(1).expectEvetType(OrderCreated::class.java).expectStateAggregate{assertThat(it.aggregateId.teatId,equalTo(teatId))}.expectState{assertThat(it.id,otNullValue())assertThat(it.customerId,equalTo(customerId))assertThat(it.address,equalTo(SHIPPING_ADDRESS))assertThat(it.items,equalTo(orderItems))assertThat(it.status,equalTo(OrderStatus.CREATED))}.verify()}/***创建订单*/@TestfucreateOrder(){mockCreateOrder()}/***创建订单-库存不足*/@TestfucreateOrderWheIvetoryShortage(){valcustomerId=GlobalIdGeerator.geerateAsStrig()valorderItem=OrderItem(GlobalIdGeerator.geerateAsStrig(),GlobalIdGeerator.geerateAsStrig(),BigDecimal.valueOf(10),10)valorderItems=listOf(orderItem)valivetoryService=object:IvetoryService{overridefugetIvetory(productId:Strig):Moo<It>{returorderItems.toFlux().filter{it.productId==productId}/**模拟库存不足*/.map{it.quatity-1}.last()}}valpricigService=object:PricigService{overridefugetProductPrice(productId:Strig):Moo<BigDecimal>{returorderItems.toFlux().filter{it.productId==productId}.map{it.price}.last()}}aggregateVerifier<Order,OrderState>().iject(DefaultCreateOrderSpec(ivetoryService,pricigService)).give().`whe`(CreateOrder(customerId,orderItems,SHIPPING_ADDRESS))/**期望:库存不足异常.*/.expectErrorType(IvetoryShortageExceptio::class.java).expectStateAggregate{/**该聚合对象处于未初始化状态,即该聚合未创建成功.*/assertThat(it.iitialized,equalTo(false))}.verify()}/***创建订单-下单价格与当前价格不一致*/@TestfucreateOrderWhePriceIcosistecy(){valcustomerId=GlobalIdGeerator.geerateAsStrig()valorderItem=OrderItem(GlobalIdGeerator.geerateAsStrig(),GlobalIdGeerator.geerateAsStrig(),BigDecimal.valueOf(10),10)valorderItems=listOf(orderItem)valivetoryService=object:IvetoryService{overridefugetIvetory(productId:Strig):Moo<It>{returorderItems.toFlux().filter{it.productId==productId}.map{it.quatity}.last()}}valpricigService=object:PricigService{overridefugetProductPrice(productId:Strig):Moo<BigDecimal>{returorderItems.toFlux().filter{it.productId==productId}/**模拟下单价格、商品定价不一致*/.map{it.price.plus(BigDecimal.valueOf(1))}.last()}}aggregateVerifier<Order,OrderState>().iject(DefaultCreateOrderSpec(ivetoryService,pricigService)).give().`whe`(CreateOrder(customerId,orderItems,SHIPPING_ADDRESS))/**期望:价格不一致异常.*/.expectErrorType(PriceIcosistecyExceptio::class.java).verify()}privatefumockPayOrder():VerifiedStage<OrderState>{valverifiedStageAfterCreateOrder=mockCreateOrder()valpreviousState=verifiedStageAfterCreateOrder.stateRootvalpayOrder=PayOrder(previousState.id,GlobalIdGeerator.geerateAsStrig(),previousState.totalAmout)returverifiedStageAfterCreateOrder.the().give()/**2.当接收到命令*/.`whe`(payOrder)/**3.1期望将会产生1个事件*/.expectEvetCout(1)/**3.2期望将会产生一个OrderPaid事件(3.1可以不需要)*/.expectEvetType(OrderPaid::class.java)/**3.3期望产生的事件状态*/.expectEvetBody<OrderPaid>{assertThat(it.amout,equalTo(payOrder.amout))}/**4.期望当前聚合状态*/.expectState{assertThat(it.address,equalTo(SHIPPING_ADDRESS))assertThat(it.paidAmout,equalTo(payOrder.amout))assertThat(it.status,equalTo(OrderStatus.PAID))}/**完成测试编排后,验证期望.*/.verify()}/***支付订单*/@TestfupayOrder(){mockPayOrder()}/***支付订单-超付*/@TestfupayOrderWheOverPay(){valverifiedStageAfterCreateOrder=mockCreateOrder()valpreviousState=verifiedStageAfterCreateOrder.stateRootvalpayOrder=PayOrder(previousState.id,GlobalIdGeerator.geerateAsStrig(),previousState.totalAmout.plus(BigDecimal.valueOf(1)))verifiedStageAfterCreateOrder.the().give()/**2.处理PayOrder命令*/.`whe`(payOrder)/**3.1期望将会产生俩个事件分别是:OrderPaid、OrderOverPaid*/.expectEvetType(OrderPaid::class.java,OrderOverPaid::class.java)/**3.2期望产生的事件状态*/.expectEvetStream{valitr=it.iterator()/**OrderPaid*/valorderPaid=itr.ext().bodyasOrderPaidassertThat(orderPaid.paid,equalTo(true))/**OrderOverPaid*/valorderOverPaid=itr.ext().bodyasOrderOverPaidassertThat(orderOverPaid.overPay,equalTo(payOrder.amout.mius(previousState.totalAmout)))}/**4.期望当前聚合状态*/.expectState{assertThat(it.paidAmout,equalTo(previousState.totalAmout))assertThat(it.status,equalTo(OrderStatus.PAID))}.verify()}/***发货*/@Testfuship(){valverifiedStageAfterPayOrder=mockPayOrder()valshipOrder=ShipOrder(verifiedStageAfterPayOrder.stateRoot.id)verifiedStageAfterPayOrder.the().give().`whe`(shipOrder).expectEvetType(OrderShipped::class.java)/**4.期望当前聚合状态*/.expectState{assertThat(it.status,equalTo(OrderStatus.SHIPPED))}.verify()}@TestfushipGiveUpaid(){valverifiedStageAfterCreateOrder=mockCreateOrder()valshipOrder=ShipOrder(verifiedStageAfterCreateOrder.stateRoot.id)verifiedStageAfterCreateOrder.the().give().`whe`(shipOrder).expectErrorType(IllegalStateExceptio::class.java).expectState{/**验证聚合状态[未]发生变更.*/assertThat(it.paidAmout,equalTo(BigDecimal.ZERO))assertThat(it.status,equalTo(OrderStatus.CREATED))}.verify()}privatefumockDeleteOrder():VerifiedStage<OrderState>{valverifiedStageAfterCreateOrder=mockCreateOrder()returverifiedStageAfterCreateOrder.the().give().`whe`(DeleteAggregate).expectEvetType(AggregateDeleted::class.java).expectStateAggregate{assertThat(it.deleted,equalTo(true))}.verify()}@TestfudeleteOrder(){mockDeleteOrder()}@TestfudeleteGiveDeleted(){valverifiedStageAfterDelete=mockDeleteOrder()verifiedStageAfterDelete.the().give().`whe`(DeleteAggregate).expectErrorType(IllegalAccessDeletedAggregateExceptio::class.java).expectError<IllegalAccessDeletedAggregateExceptio>{assertThat(it.aggregateId,equalTo(verifiedStageAfterDelete.stateAggregate.aggregateId))}.expectStateAggregate{assertThat(it.deleted,equalTo(true))}.verify()}}设计聚合建模SigleClassIheritacePatterAggregatioPatter加载聚合聚合状态流发送命令命令与事件流Saga-OrderProcessMaager(Demo)点击空白处退出提示
评论