{"id":13631359,"url":"https://github.com/itswuanran/enode","last_synced_at":"2025-08-15T00:38:54.595Z","repository":{"id":37285263,"uuid":"165245292","full_name":"itswuanran/enode","owner":"itswuanran","description":"DDD 框架","archived":false,"fork":false,"pushed_at":"2023-10-24T09:30:47.000Z","size":3873,"stargazers_count":210,"open_issues_count":0,"forks_count":55,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-08-13T03:34:47.598Z","etag":null,"topics":["clean-architecture","cqrs","ddd","event-sourcing","hexagonal-architecture"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/itswuanran.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","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}},"created_at":"2019-01-11T13:06:11.000Z","updated_at":"2025-07-22T09:25:30.000Z","dependencies_parsed_at":"2023-01-19T11:18:39.941Z","dependency_job_id":"11377894-230e-4e33-9925-ad6548131e20","html_url":"https://github.com/itswuanran/enode","commit_stats":null,"previous_names":["itswuanran/enode","anruence/enode"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/itswuanran/enode","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itswuanran%2Fenode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itswuanran%2Fenode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itswuanran%2Fenode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itswuanran%2Fenode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/itswuanran","download_url":"https://codeload.github.com/itswuanran/enode/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itswuanran%2Fenode/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270505984,"owners_count":24596505,"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","status":"online","status_checked_at":"2025-08-14T02:00:10.309Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["clean-architecture","cqrs","ddd","event-sourcing","hexagonal-architecture"],"created_at":"2024-08-01T22:02:22.285Z","updated_at":"2025-08-15T00:38:54.563Z","avatar_url":"https://github.com/itswuanran.png","language":"Kotlin","funding_links":[],"categories":["Kotlin"],"sub_categories":[],"readme":"## 框架简介\n\n`enode`是基于`JVM`平台，为业务实践`Domain Driven Design`思想而落地的一个应用框架，使用`CQRS`, `Event Sourcing`设计模式，让开发者可以专注于业务模型建模和业务逻辑开发\n\n## 框架特色\n- `Reactive`\n  - `enode`是完全响应式的框架，是实现高吞吐的核心设计\n  - `db`层面使用了异步驱动，实现全链路异步\n  - 针对`IO`密集型操作，集成了`kotlin coroutine`\n- `Event Sourcing`\n  - 聚合根的事件完全持久化，记录聚合根的状态变化，让`C`端的数据可追溯，数据持久化变得通用化\n- `Event Driven`\n  - 业务流程以事件驱动为核心，让研发更聚焦业务中领域事件的建设和积累\n  - 先进的`Saga`机制，以事件驱动的流程管理器（`Process Manager`）的方式支持一个用户操作跨多个聚合根的业务场景，如订单处理，从而避免分布式事务的使用\n- `CQRS`\n  - 基于`CQRS`架构思想，`enode`解决了`CQRS`架构的`C`端的高并发写的问题，以及`CQ`两端数据同步的顺序性保证和幂等性 \n  - 支持`Fire And Forget`和`Fire And Wait`两种方式返回命令执行结果\n- `Fast and Flexible`\n  - 聚合根常驻内存（`In-Memory Domain Model`），在设计上尽可能的避免了聚合根重建，可以完全以`OO`的方式来设计实现聚合根，不必为`ORM`的阻抗失衡而烦恼\n  - 聚合根的处理基于`Actor`思想，乐观并发控制，无锁，在事件持久化层面使用`Group Commit Domain Event`提高写性能\n\n`enode`在架构层面严格规范了研发人员该如何写代码，要求用`DDD`的方式思考，严格遵守聚合内强一致性、聚合之间最终一致性的原则\n\n在设计上遵循`SOLID`，以下均可扩展替换成自建\n- 针对`IoC`容器，目前`SpringBoot`友好适配\n- 针对`CommandBus`，只要求最基础的队列能力，目前适配了`Kafka`、`RocketMQ`、`Pulsar`、`AMQP`\n- 针对`EventStore`，适配了`MySQL`、`PostgreSQL`、`MongoDB`\n- 针对`ReplyService`，要求实现点对点通信模型，实现Command处理结果的通知\n\n## 使用约束\n\n- **一个**命令一次只能修改**一个**聚合根\n- **聚合间**只能通过**领域消息**交互\n- 聚合内**强一致性**\n- 聚合间**最终一致性**\n\n## 发版记录\n\n[CHANGELOG](CHANGELOG.md)\n\n## 整体架构\n\n![](enode-arch.jpg)\n\n## `Saga`的两种模式\n\n- 编排（`Choreography`）\n  参与者（子事务）之间的调用、分配、决策和排序，通过交换事件进行进行。是一种去中心化的模式，参与者之间通过消息机制进行沟通，通过监听器的方式监听其他参与者发出的消息，从而执行后续的逻辑处理。\n\n\u003e `enode`中使用的就是这种模式\n\n- 控制（`Orchestration`）\n  提供一个控制类，方便参与者之间的协调工作。事务执行的命令从控制类发起，按照逻辑顺序请求`Saga`\n  的参与者，从参与者那里接受到反馈以后，控制类在发起向其他参与者的调用。所有`Saga`的参与者都围绕这个控制类进行沟通和协调工作。\n\n\u003e [`Apache ServiceComb`](https://servicecomb.apache.org/) 使用的是这种模式\n\n### 编程模型\n\n新增了三个注解，系统限定了只扫描`@Command`和`@Event`标识的类，执行的方法上需要添加`@Subscribe`注解：\n\n- `@Command`\n- `@Event`\n- `@Subscribe`\n\n启动时会扫描包路径下的注解，注册成`Spring Bean`，和`@Component`作用相同。\n## 基础组件依赖\n\n### `docker`部署\n定义了`docker-compose.yml`，搭配`docker-compose`快速的在启动一套运行环境，用于应用的测试\n\n```bash\ndocker-compose up -d\n```\n\n## 消息\n\n- 目前enode函数调用的实现是放在`kotlin coroutine`中来执行的，这里涉及到实际执行的任务类型，针对计算密集型和IO密集型的任务，目前没有做可定制化的配置，后续的版本会考虑加上，\n  **使用也很简单，`@Subscribe` 方法体加上`suspend`标记即可**。\n\n- **针对`Java`异步编程做了深度优化，支持`CommandHandler`和`EventHandler`中定义`CompletableFuture`\n  返回值，阻塞调用封装在协程中，避免使用`#join() #get()`等阻塞代码，同时也支持`kotlin suspend`**\n\n## 详细介绍\n\n- [enode核心概念介绍](./docs/intro.md)\n- [enode使用说明](./docs/usage.md)\n\n## 最佳实践\n\n可参考[samples](samples)模块中的例子 \n\n转账的例子中，转账的业务场景，涉及了三个聚合根：\n- 银行存款交易记录，表示一笔银行存款交易\n- 银行转账交易记录，表示一笔银行内账户之间的转账交易\n- 银行账户聚合根，封装银行账户余额变动的数据一致性\n\n### `command-web`启动\n\n- `CQRS`架构中的`Command`端应用\n\n主要用来接收来自用户的`Command`请求，核心是将`Command`发送到消息队列。\n\n### `command-consumer`启动\n\n- 消费`Command`队列中的消息的服务\n\n\u003e 将领域事件消息持久化才算是`Command`执行成功，`Command`执行的结果可以通过发送命令时注册的监听器获取。\n\n### `event-consumer`启动\n\n- 领域事件处理服务\n\n\u003e 事件可能会多次投递，所以需要消费端逻辑保证幂等处理，这里框架无法完成支持，需要开发者自己实现。\n\n## See Also\n[conference](https://github.com/anruence/conference)\n\n## 参考项目\n\n- https://github.com/tangxuehua/enode\n- https://github.com/coffeewar/enode-master\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitswuanran%2Fenode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fitswuanran%2Fenode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitswuanran%2Fenode/lists"}