An open API service indexing awesome lists of open source software.

https://github.com/ahoo-wang/wow

Modern Reactive CQRS Architecture Microservice development framework based on DDD and EventSourcing | 基于 DDD & EventSourcing 的现代响应式 CQRS 架构微服务开发框架
https://github.com/ahoo-wang/wow

architecture axon cqrs ddd domain-driven-design elasticsearch event-driven event-sourcing high-performance java kafka kotlin microservice mongodb opentelemetry reactive-programming spring spring-boot webflux

Last synced: about 17 hours ago
JSON representation

Modern Reactive CQRS Architecture Microservice development framework based on DDD and EventSourcing | 基于 DDD & EventSourcing 的现代响应式 CQRS 架构微服务开发框架

Awesome Lists containing this project

README

          


Wow:A Modern Reactive CQRS Architecture Microservice development framework based on DDD and EventSourcing

# Wow : Modern Reactive CQRS Architecture Microservice development framework based on DDD and EventSourcing

[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://github.com/Ahoo-Wang/Wow/blob/main/LICENSE)
[![GitHub release](https://img.shields.io/github/release/Ahoo-Wang/Wow.svg)](https://github.com/Ahoo-Wang/Wow/releases)
[![Maven Central Version](https://img.shields.io/maven-central/v/me.ahoo.wow/wow-core)](https://central.sonatype.com/artifact/me.ahoo.wow/wow-core)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/cfc724df22db4f9387525258c8a59609)](https://app.codacy.com/gh/Ahoo-Wang/Wow/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
[![codecov](https://codecov.io/gh/Ahoo-Wang/Wow/branch/main/graph/badge.svg?token=uloJrLoQir)](https://codecov.io/gh/Ahoo-Wang/Wow)
[![Integration Test Status](https://github.com/Ahoo-Wang/Wow/actions/workflows/integration-test.yml/badge.svg)](https://github.com/Ahoo-Wang/Wow)
[![Awesome Kotlin Badge](https://kotlin.link/awesome-kotlin.svg)](https://github.com/KotlinBy/awesome-kotlin)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/Ahoo-Wang/Wow)

**Domain-Driven** | **Event-Driven** | **Test-Driven** | **Declarative-Design** | **Reactive Programming** | **Command Query Responsibility Segregation** | **Event Sourcing**

> [中文文档](https://wow.ahoo.me/zh/) | [English Document](https://wow.ahoo.me/)

## Quick Start

Use [Wow Project Template](https://github.com/Ahoo-Wang/wow-project-template) to quickly create a DDD project based on the Wow framework.

## Features Overview


Wow-Features

## Architecture


Wow-Architecture

### Command Processing Propagation Chain


Wow-WaitingForChain

## Performance Test (Example)

- Test Code: [Example](./example)
- Test Case: Add To Shopping Cart / Create Order
- Command `WaitStrategy`: `SENT`、`PROCESSED`

### Deployment

- [Redis](deploy/example/perf/redis.yaml)
- [MongoDB](deploy/example/perf/mongo.yaml)
- [Kafka](deploy/example/perf/kafka.yaml)
- [Application-Config](deploy/example/perf/config/mongo_kafka_redis.yaml)
- [Application-Deployment](deploy/example/perf/deployment.yaml)

### Test Report

#### Add To Shopping Cart

- [Request](deploy/example/request/AddCartItem.http)
- [Detailed Report(PDF)-SENT](./document/example/perf/Example.Cart.Add@SENT.pdf)
- [Detailed Report(PDF)-PROCESSED](./document/example/perf/Example.Cart.Add@PROCESSED.pdf)

> `WaitStrategy`:`SENT` Mode, The `AddCartItem` command write request API After 2 minutes of stress testing, the average TPS was *59625*, the peak was *82312*, and the average response time was *29* ms.


AddCartItem-SENT

> `WaitStrategy`:`PROCESSED` Mode, The `AddCartItem` command write request API After 2 minutes of stress testing, the average TPS was *18696*, the peak was *24141*, and the average response time was *239* ms.


AddCartItem-PROCESSED

#### Create Order

- [Request](deploy/example/request/CreateOrder.http)
- [Detailed Report(PDF)-SENT](./document/example/perf/Example.Order.Create@SENT.pdf)
- [Detailed Report(PDF)-PROCESSED](./document/example/perf/Example.Order.Create@PROCESSED.pdf)

> `WaitStrategy`:`SENT` Mode, The `CreateOrder` command write request API After 2 minutes of stress testing, the average TPS was *47838*, the peak was *86200*, and the average response time was *217* ms.


CreateOrder-SENT

> `WaitStrategy`:`PROCESSED` Mode, The `CreateOrder` command write request API After 2 minutes of stress testing, the average TPS was *18230*, the peak was *25506*, and the average response time was *268* ms.


CreateOrder-PROCESSED

## Event Sourcing


Wow-EventSourcing

## Observability


Wow-Observability

## OpenAPI (Spring WebFlux Integration)

> Automatically register the `Command` routing processing function (`HandlerFunction`), and developers only need to
> write the domain model to complete the service development.


Wow-Spring-WebFlux-Integration

## Test suite: 80%+ test coverage is very easy

> Given -> When -> Expect .


Wow-CI-Flow

## Preconditions

- Understanding **Domain Driven Design**:《Implementing Domain-Driven Design》,《Domain-Driven Design: Tackling Complexity
in the Heart of Software》
- Understanding **Command Query Responsibility Segregation**(CQRS)
- Understanding **EventSourcing**
- Understanding **Reactive Programming**

### Order Service(Kotlin)

[Example-Order](./example)

### Transfer(JAVA)

[Example-Transfer](./example/transfer)

## Unit Test Suite

### 80%+ test coverage is very easy.

![Test Coverage](./document/example/example-domain-jococo.png)

> Given -> When -> Expect .

### Aggregate Unit Test (`AggregateVerifier`)

[Aggregate Test](./example/example-domain/src/test/kotlin/me/ahoo/wow/example/domain/order/OrderTest.kt)

```kotlin
class CartSpec : AggregateSpec({
on {
val ownerId = generateGlobalId()
val addCartItem = AddCartItem(
productId = "productId",
quantity = 1,
)
givenOwnerId(ownerId)
whenCommand(addCartItem) {
expectNoError()
expectEventType(CartItemAdded::class)
expectState {
items.assert().hasSize(1)
}
expectStateAggregate {
ownerId.assert().isEqualTo(ownerId)
}
fork {
val removeCartItem = RemoveCartItem(
productIds = setOf(addCartItem.productId),
)
whenCommand(removeCartItem) {
expectEventType(CartItemRemoved::class)
}
}
fork {
whenCommand(DefaultDeleteAggregate) {
expectEventType(DefaultAggregateDeleted::class)
expectStateAggregate {
deleted.assert().isTrue()
}

fork {
whenCommand(DefaultDeleteAggregate) {
expectErrorType(IllegalAccessDeletedAggregateException::class)
}
}
fork {
whenCommand(DefaultRecoverAggregate) {
expectNoError()
expectStateAggregate {
deleted.assert().isFalse()
}
fork {
whenCommand(DefaultRecoverAggregate) {
expectErrorType(IllegalStateException::class)
}
}
}
}
}
}
}
}
}
)
```

### Saga Unit Test (`SagaVerifier`)

[Saga Test](./example/example-domain/src/test/kotlin/me/ahoo/wow/example/domain/cart/CartSagaTest.kt)

```kotlin
class CartSagaSpec : SagaSpec({
on {
val ownerId = generateGlobalId()
val orderItem = OrderItem(
id = generateGlobalId(),
productId = generateGlobalId(),
price = BigDecimal.valueOf(10),
quantity = 10,
)
whenEvent(
event = mockk {
every {
items
} returns listOf(orderItem)
every {
fromCart
} returns true
},
ownerId = ownerId
) {
expectCommandType(RemoveCartItem::class)
expectCommand {
aggregateId.id.assert().isEqualTo(ownerId)
body.productIds.assert().hasSize(1)
body.productIds.assert().first().isEqualTo(orderItem.productId)
}
}
}
on {
name("NotFromCart")
val orderItem = OrderItem(
id = generateGlobalId(),
productId = generateGlobalId(),
price = BigDecimal.valueOf(10),
quantity = 10,
)
whenEvent(
event = mockk {
every {
items
} returns listOf(orderItem)
every {
fromCart
} returns false
},
ownerId = generateGlobalId()
) {
expectNoCommand()
}
}
})
```

## Design

### Modeling

| **Single Class** | **Inheritance Pattern** | **Aggregation Pattern** |
|----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------|
| ![Single Class - Modeling](./document/design/assets/Modeling-Single-Class-Pattern.svg) | ![Inheritance Pattern- Modeling](./document/design/assets/Modeling-Inheritance-Pattern.svg) | ![Aggregation Pattern- Modeling](./document/design/assets/Modeling-Aggregation-Pattern.svg) |

### Load Aggregate


Load Aggregate

### Aggregate State Flow


Aggregate State Flow

### Send Command


Send Command

### Command And Event Flow


Command And Event Flow

## Event Compensation

### Use Case


Event-Compensation-UserCase

### Execution Sequence Diagram


Event-Compensation

### Dashboard


Compensation-Dashboard


Compensation-Dashboard


Compensation-Dashboard


Compensation-Dashboard-Error