{"id":15137850,"url":"https://github.com/ahoo-wang/wow","last_synced_at":"2026-04-08T04:02:28.664Z","repository":{"id":157710904,"uuid":"628167080","full_name":"Ahoo-Wang/Wow","owner":"Ahoo-Wang","description":"Modern Reactive CQRS Architecture Microservice development framework based on DDD and EventSourcing | 基于 DDD \u0026 EventSourcing 的现代响应式 CQRS 架构微服务开发框架","archived":false,"fork":false,"pushed_at":"2025-04-07T01:31:47.000Z","size":23108,"stargazers_count":233,"open_issues_count":3,"forks_count":30,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-04-07T02:28:39.140Z","etag":null,"topics":["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"],"latest_commit_sha":null,"homepage":"https://wow.ahoo.me/","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Ahoo-Wang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-15T05:28:03.000Z","updated_at":"2025-04-05T08:58:29.000Z","dependencies_parsed_at":"2023-10-03T04:54:31.223Z","dependency_job_id":"ee30415a-bc5d-4ed6-b25a-16c56572642e","html_url":"https://github.com/Ahoo-Wang/Wow","commit_stats":{"total_commits":1258,"total_committers":5,"mean_commits":251.6,"dds":"0.27344992050874406","last_synced_commit":"013c436ec1ea55444a010749120c32528c422138"},"previous_names":[],"tags_count":366,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ahoo-Wang%2FWow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ahoo-Wang%2FWow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ahoo-Wang%2FWow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ahoo-Wang%2FWow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ahoo-Wang","download_url":"https://codeload.github.com/Ahoo-Wang/Wow/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248633748,"owners_count":21136908,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["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"],"created_at":"2024-09-26T07:02:41.990Z","updated_at":"2026-04-01T17:12:43.299Z","avatar_url":"https://github.com/Ahoo-Wang.png","language":"Kotlin","readme":"\u003cp align=\"center\" style=\"text-align:center;\"\u003e\n  \u003cimg width=\"150\" src=\"document/design/assets/logo.svg\" alt=\"Wow:A Modern Reactive CQRS Architecture Microservice development framework based on DDD and EventSourcing\"/\u003e\n\u003c/p\u003e\n\n# Wow : Modern Reactive CQRS Architecture Microservice development framework based on DDD and EventSourcing\n\n[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://github.com/Ahoo-Wang/Wow/blob/main/LICENSE)\n[![GitHub release](https://img.shields.io/github/release/Ahoo-Wang/Wow.svg)](https://github.com/Ahoo-Wang/Wow/releases)\n[![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)\n[![Codacy Badge](https://app.codacy.com/project/badge/Grade/cfc724df22db4f9387525258c8a59609)](https://app.codacy.com/gh/Ahoo-Wang/Wow/dashboard?utm_source=gh\u0026utm_medium=referral\u0026utm_content=\u0026utm_campaign=Badge_grade)\n[![codecov](https://codecov.io/gh/Ahoo-Wang/Wow/branch/main/graph/badge.svg?token=uloJrLoQir)](https://codecov.io/gh/Ahoo-Wang/Wow)\n[![Integration Test Status](https://github.com/Ahoo-Wang/Wow/actions/workflows/integration-test.yml/badge.svg)](https://github.com/Ahoo-Wang/Wow)\n[![Awesome Kotlin Badge](https://kotlin.link/awesome-kotlin.svg)](https://github.com/KotlinBy/awesome-kotlin)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/Ahoo-Wang/Wow)\n\n**Domain-Driven** | **Event-Driven** | **Test-Driven** | **Declarative-Design** | **Reactive Programming** | **Command Query Responsibility Segregation** | **Event Sourcing**\n\n\u003e [中文文档](https://wow.ahoo.me/zh/) | [English Document](https://wow.ahoo.me/)\n\n## Spring Boot Version Compatibility\n\n\u003e **Wow 6.x** supports Spring Boot 3.x , base Java 17\n\u003e\n\u003e **Wow 8.x** supports Spring Boot 4.x , base Java 17\n\n## Quick Start\n\nUse [Wow Project Template](https://github.com/Ahoo-Wang/wow-project-template) to quickly create a DDD project based on the Wow framework.\n\n## Features Overview\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"documentation/docs/public/images/Features.png\" alt=\"Wow-Features\"/\u003e\n\u003c/p\u003e\n\n## Architecture\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg width=\"95%\" src=\"documentation/docs/public/images/Architecture.svg\" alt=\"Wow-Architecture\"/\u003e\n\u003c/p\u003e\n\n### Command Processing Propagation Chain\n\n\u003cp align=\"center\" style=\"text-align:center;\"\u003e\n  \u003cimg  width=\"95%\" src=\"documentation/docs/public/images/wait/WaitingForChain.svg\" alt=\"Wow-WaitingForChain\"/\u003e\n\u003c/p\u003e\n\n## Performance Test (Example)\n\n- Test Code: [Example](./example)\n- Test Case: Add To Shopping Cart / Create Order\n- Command `WaitStrategy`: `SENT`、`PROCESSED`\n\n### Deployment\n\n- [Redis](deploy/example/perf/redis.yaml)\n- [MongoDB](deploy/example/perf/mongo.yaml)\n- [Kafka](deploy/example/perf/kafka.yaml)\n- [Application-Config](deploy/example/perf/config/mongo_kafka_redis.yaml)\n- [Application-Deployment](deploy/example/perf/deployment.yaml)\n\n### Test Report\n\n#### Add To Shopping Cart\n\n- [Request](deploy/example/request/AddCartItem.http)\n- [Detailed Report(PDF)-SENT](./document/example/perf/Example.Cart.Add@SENT.pdf)\n- [Detailed Report(PDF)-PROCESSED](./document/example/perf/Example.Cart.Add@PROCESSED.pdf)\n\n\u003e `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.\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"./document/example/perf/Example.Cart.Add@SENT.png\" alt=\"AddCartItem-SENT\"/\u003e\n\u003c/p\u003e\n\n\u003e `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.\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"./document/example/perf/Example.Cart.Add@PROCESSED.png\" alt=\"AddCartItem-PROCESSED\"/\u003e\n\u003c/p\u003e\n\n#### Create Order\n\n- [Request](deploy/example/request/CreateOrder.http)\n- [Detailed Report(PDF)-SENT](./document/example/perf/Example.Order.Create@SENT.pdf)\n- [Detailed Report(PDF)-PROCESSED](./document/example/perf/Example.Order.Create@PROCESSED.pdf)\n\n\u003e `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.\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"./document/example/perf/Example.Order.Create@SENT.png\" alt=\"CreateOrder-SENT\"/\u003e\n\u003c/p\u003e\n\n\u003e `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.\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"./document/example/perf/Example.Order.Create@PROCESSED.png\" alt=\"CreateOrder-PROCESSED\"/\u003e\n\u003c/p\u003e\n\n## Event Sourcing\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"./document/design/assets/EventSourcing.svg\" alt=\"Wow-EventSourcing\"/\u003e\n\u003c/p\u003e\n\n## Observability\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"./document/design/assets/OpenTelemetry.png\" alt=\"Wow-Observability\"/\u003e\n\u003c/p\u003e\n\n## OpenAPI (Spring WebFlux Integration)\n\n\u003e Automatically register the `Command` routing processing function (`HandlerFunction`), and developers only need to\n\u003e write the domain model to complete the service development.\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"document/design/assets/OpenAPI-Swagger.png\" alt=\"Wow-Spring-WebFlux-Integration\"/\u003e\n\u003c/p\u003e\n\n## Test suite: 80%+ test coverage is very easy\n\n\u003e Given -\u003e When -\u003e Expect .\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"./document/design/assets/CI-Flow.png\" alt=\"Wow-CI-Flow\"/\u003e\n\u003c/p\u003e\n\n## Preconditions\n\n- Understanding **Domain Driven Design**：《Implementing Domain-Driven Design》,《Domain-Driven Design: Tackling Complexity\n  in the Heart of Software》\n- Understanding **Command Query Responsibility Segregation**(CQRS)\n- Understanding **EventSourcing**\n- Understanding **Reactive Programming**\n\n### Order Service（Kotlin）\n\n[Example-Order](./example)\n\n### Transfer（JAVA）\n\n[Example-Transfer](./example/transfer)\n\n## Unit Test Suite\n\n### 80%+ test coverage is very easy.\n\n![Test Coverage](./document/example/example-domain-jococo.png)\n\n\u003e Given -\u003e When -\u003e Expect .\n\n### Aggregate Unit Test (`AggregateVerifier`)\n\n[Aggregate Test](./example/example-domain/src/test/kotlin/me/ahoo/wow/example/domain/order/OrderTest.kt)\n\n```kotlin\nclass CartSpec : AggregateSpec\u003cCart, CartState\u003e({\n  on {\n    val ownerId = generateGlobalId()\n    val addCartItem = AddCartItem(\n      productId = \"productId\",\n      quantity = 1,\n    )\n    givenOwnerId(ownerId)\n    whenCommand(addCartItem) {\n      expectNoError()\n      expectEventType(CartItemAdded::class)\n      expectState {\n        items.assert().hasSize(1)\n      }\n      expectStateAggregate {\n        ownerId.assert().isEqualTo(ownerId)\n      }\n      fork {\n        val removeCartItem = RemoveCartItem(\n          productIds = setOf(addCartItem.productId),\n        )\n        whenCommand(removeCartItem) {\n          expectEventType(CartItemRemoved::class)\n        }\n      }\n      fork {\n        whenCommand(DefaultDeleteAggregate) {\n          expectEventType(DefaultAggregateDeleted::class)\n          expectStateAggregate {\n            deleted.assert().isTrue()\n          }\n\n          fork {\n            whenCommand(DefaultDeleteAggregate) {\n              expectErrorType(IllegalAccessDeletedAggregateException::class)\n            }\n          }\n          fork {\n            whenCommand(DefaultRecoverAggregate) {\n              expectNoError()\n              expectStateAggregate {\n                deleted.assert().isFalse()\n              }\n              fork {\n                whenCommand(DefaultRecoverAggregate) {\n                  expectErrorType(IllegalStateException::class)\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}\n)\n```\n\n### Saga Unit Test (`SagaVerifier`)\n\n[Saga Test](./example/example-domain/src/test/kotlin/me/ahoo/wow/example/domain/cart/CartSagaTest.kt)\n\n```kotlin\nclass CartSagaSpec : SagaSpec\u003cCartSaga\u003e({\n  on {\n    val ownerId = generateGlobalId()\n    val orderItem = OrderItem(\n      id = generateGlobalId(),\n      productId = generateGlobalId(),\n      price = BigDecimal.valueOf(10),\n      quantity = 10,\n    )\n    whenEvent(\n      event = mockk\u003cOrderCreated\u003e {\n        every {\n          items\n        } returns listOf(orderItem)\n        every {\n          fromCart\n        } returns true\n      },\n      ownerId = ownerId\n    ) {\n      expectCommandType(RemoveCartItem::class)\n      expectCommand\u003cRemoveCartItem\u003e {\n        aggregateId.id.assert().isEqualTo(ownerId)\n        body.productIds.assert().hasSize(1)\n        body.productIds.assert().first().isEqualTo(orderItem.productId)\n      }\n    }\n  }\n  on {\n    name(\"NotFromCart\")\n    val orderItem = OrderItem(\n      id = generateGlobalId(),\n      productId = generateGlobalId(),\n      price = BigDecimal.valueOf(10),\n      quantity = 10,\n    )\n    whenEvent(\n      event = mockk\u003cOrderCreated\u003e {\n        every {\n          items\n        } returns listOf(orderItem)\n        every {\n          fromCart\n        } returns false\n      },\n      ownerId = generateGlobalId()\n    ) {\n      expectNoCommand()\n    }\n  }\n})\n```\n\n## Design\n\n### Modeling\n\n| **Single Class**                                                                       | **Inheritance Pattern**                                                                     | **Aggregation Pattern**                                                                     |\n|----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------|\n| ![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) |\n\n### Load Aggregate\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"./document/design/assets/Load-Aggregate.svg\" alt=\"Load Aggregate\"/\u003e\n\u003c/p\u003e\n\n### Aggregate State Flow\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"./document/design/assets/Aggregate-State-Flow.svg\" alt=\"Aggregate State Flow\"/\u003e\n\u003c/p\u003e\n\n### Send Command\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"./document/design/assets/Send-Command.svg\" alt=\"Send Command\"/\u003e\n\u003c/p\u003e\n\n### Command And Event Flow\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"./document/design/assets/Command-Event-Flow.svg\" alt=\"Command And Event Flow\"/\u003e\n\u003c/p\u003e\n\n## Event Compensation\n\n### Use Case\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"documentation/docs/public/images/compensation/usercase.svg\" alt=\"Event-Compensation-UserCase\"/\u003e\n\u003c/p\u003e\n\n### Execution Sequence Diagram\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"documentation/docs/public/images/compensation/process-sequence-diagram.svg\" alt=\"Event-Compensation\"/\u003e\n\u003c/p\u003e\n\n### Dashboard\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"documentation/docs/public/images/compensation/dashboard.png\" alt=\"Compensation-Dashboard\"/\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"documentation/docs/public/images/compensation/dashboard-apply-retry-spec.png\" alt=\"Compensation-Dashboard\"/\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"documentation/docs/public/images/compensation/dashboard-succeeded.png\" alt=\"Compensation-Dashboard\"/\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003e\n  \u003cimg src=\"documentation/docs/public/images/compensation/dashboard-error.png\" alt=\"Compensation-Dashboard-Error\"/\u003e\n\u003c/p\u003e\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fahoo-wang%2Fwow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fahoo-wang%2Fwow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fahoo-wang%2Fwow/lists"}