genies_derive
Genies 框架的过程宏库,为 DDD 聚合根、领域事件、配置管理、Dapr 事件消费、HTTP 请求包装和字段级权限控制提供派生宏和属性宏。
概述
genies_derive 提供 7 个核心宏,简化 DDD + Dapr + Casbin 应用中的常见模式:
| 宏 | 类型 | 用途 |
|---|---|---|
#[derive(Aggregate)] |
派生宏 | DDD 聚合根实现 |
#[derive(DomainEvent)] |
派生宏 | 领域事件类型实现 |
#[derive(Config)] |
派生宏 | 从 YAML/环境变量加载配置 |
#[derive(ConfigCore)] |
派生宏 | 内部配置(避免循环依赖) |
#[topic(...)] |
属性宏 | Dapr topic 消费,支持 Redis 幂等 |
#[wrapper(...)] |
属性宏 | HTTP 请求包装,支持 JWT 自动刷新 |
#[casbin] |
属性宏 | 字段级权限控制 |
快速开始
[]
= { = "../path/to/genies_derive" }
= { = "../path/to/genies" }
宏参考
1. #[derive(Aggregate)] - 聚合根
实现 AggregateType、WithAggregateId 以及可选的 InitializeAggregate trait。
属性说明:
| 属性 | 必需 | 说明 |
|---|---|---|
#[aggregate_type("Name")] |
否 | 覆盖聚合类型名(默认:结构体名) |
#[id_field(field_name)] |
否 | 指定 ID 字段 |
#[initialize_with_defaults] |
否 | 生成 InitializeAggregate 实现(需配合 id_field) |
示例:
use Aggregate;
use ;
// 生成的 trait:
// - AggregateType::aggregate_type(&self) -> String // 返回 "Order"
// - AggregateType::atype() -> String // 静态版本
// - WithAggregateId::aggregate_id(&self) -> &String
// - InitializeAggregate::initialize(id: String) -> Order
2. #[derive(DomainEvent)] - 领域事件
为事件溯源模式实现 DomainEvent trait。
属性说明:
| 属性 | 必需 | 说明 |
|---|---|---|
#[event_type("Name")] |
否 | 覆盖事件类型(默认:结构体/枚举变体名) |
#[event_type_version("V1")] |
否 | 事件版本(默认:"V0") |
#[event_source("service")] |
否 | 事件来源标识(默认:"") |
结构体示例:
use DomainEvent;
use ;
// 生成: DomainEvent trait,包含 event_type()、event_type_version()、event_source()、json()
枚举示例:
3. #[derive(Config)] - 配置
生成从 YAML 文件和环境变量加载配置的方法。
字段属性:
| 属性 | 说明 |
|---|---|
#[config(default = "value")] |
字段默认值 |
示例:
use Config;
use ;
// 生成的方法:
// - AppConfig::default() -> Self
// - AppConfig::from_file(path: &str) -> Result<Self, ConfigError>
// - AppConfig::from_sources(path: &str) -> Result<Self, ConfigError>
// - AppConfig::load_env(&mut self) -> Result<(), ConfigError>
// - AppConfig::merge(&mut self, other: Self)
// - AppConfig::validate(&self) -> Result<(), ConfigError>
环境变量支持:
# 支持两种格式:
# 小写
# SCREAMING_SNAKE_CASE
4. #[derive(ConfigCore)] - 内部配置
与 Config 相同,但使用 genies_core::error::ConfigError 而非 genies::core::error::ConfigError。用于内部以避免循环依赖。
5. #[topic(...)] - Dapr Topic 消费
将异步函数转换为 Dapr topic 消费者,支持基于 Redis 的幂等性。
属性说明:
| 属性 | 必需 | 说明 |
|---|---|---|
name = "topic_name" |
否 | Topic 名称(默认:聚合类型) |
pubsub = "pubsub_name" |
否 | PubSub 组件(默认:"messagebus") |
metadata = "k1=v1,k2=v2" |
否 | Topic 元数据 |
示例:
use topic;
use Executor;
pub async
生成的代码:
- 处理函数:
handle_order_created(tx, event)- 你的业务逻辑 - Salvo 处理器:
handle_order_created_hoop- Dapr 的 HTTP 处理器 - Dapr 配置:
handle_order_created_dapr()- 返回DaprTopicSubscription - 路由:
handle_order_created_hoop_router()- Salvo 路由 - 自动注册: 通过
inventory::submit!
幂等性流程:
Dapr 消息 → 解析 CloudEvent → 提取 event_type
↓
检查 Redis key: {server}-{handler}-{event_type}-{message_id}
↓
如果 CONSUMING: 稍后重试
如果 CONSUMED: 跳过
如果不存在: SET NX(原子操作)→ 处理 → SET CONSUMED
6. #[wrapper(...)] - HTTP 请求包装
包装 feignhttp 请求,在 401 错误时自动刷新 JWT token。
示例:
use wrapper;
use get;
pub async
生成的代码:
// 带 Authorization header 的原函数
pub async
// 带自动 token 刷新的包装函数
pub async
7. #[casbin] - 字段级权限控制
生成自定义 Serialize 和 Salvo Writer 实现,用于字段级权限过滤。
示例:
use casbin;
use Deserialize;
use ToSchema;
自动嵌套检测:
宏自动检测非原始类型并递归过滤:
- 普通结构体字段:
Address - Option 包装:
Option<Address> - Vec 包装:
Vec<BankAccount>
生成的代码:
策略示例:
-- 禁止 bob 读取 User.email 字段
INSERT INTO casbin_rules (ptype, v0, v1, v2, v3)
VALUES ('p', 'bob', 'User.email', 'read', 'deny');
-- 禁止 guest 角色读取 phone 字段
INSERT INTO casbin_rules (ptype, v0, v1, v2, v3)
VALUES ('p', 'guest', 'User.phone', 'read', 'deny');
依赖项
- proc-macro2 / quote / syn - 过程宏基础设施
- genies_core - ConfigCore 的错误类型
- serde / serde_yaml - 配置解析
- convert_case - 环境变量名转换
- async-trait - 异步 trait 支持
与其他 Crate 的集成
| 宏 | 集成对象 |
|---|---|
Aggregate |
genies_ddd::aggregate traits |
DomainEvent |
genies_ddd::event traits |
Config / ConfigCore |
genies_core::error::ConfigError |
#[topic] |
genies_dapr、genies_context::CONTEXT、Redis |
#[wrapper] |
genies_core::jwt、genies_context::REMOTE_TOKEN |
#[casbin] |
genies_auth、casbin::Enforcer、Salvo |
调试模式
启用 debug_mode 特性可在编译时打印生成的代码:
[]
= { = "...", = ["debug_mode"] }
许可证
MIT