⚡ 什么是 Reducer?
Reducer 是修改数据库状态的唯一方式。它像 RPC 端点,客户端调用它来执行业务逻辑。
- 事务性 - 每个 Reducer 在事务中执行
- 原子性 - 成功或失败,无中间状态
- 隔离性 - 并发 Reducer 不互相干扰
📝 定义 Reducer
#[spacetimedb::reducer]
pub fn send_message(ctx: &ReducerContext, text: String) {
// 验证
if text.is_empty() {
return;
}
// 插入数据
ctx.db.messages().insert(Message {
id: 0,
sender: ctx.sender,
text,
});
}🔄 事务保证
每个 Reducer 自动在事务中执行:
// 如果 Reducer 失败,所有更改回滚
#[spacetimedb::reducer]
pub fn transfer(ctx: &ReducerContext, to: Identity, amount: u64) -> Result<(), String> {
let from_balance = ctx.db.balances().id().find(ctx.sender).ok_or("No balance")?;
if from_balance.amount < amount {
return Err("Insufficient funds");
}
// 这些操作要么全部成功,要么全部回滚
ctx.db.balances().id().update(Balance { amount: from_balance.amount - amount, ..from_balance });
ctx.db.balances().id().update(/* ... */);
Ok(())
}📤 返回值
Reducer 可以返回:
()- 无返回值Result<(), String>- 错误信息Result<(), E>- 自定义错误类型
👤 访问调用者
#[spacetimedb::reducer]
pub fn my_reducer(ctx: &ReducerContext) {
// 调用者身份
let sender: Identity = ctx.sender;
// 连接 ID
let connection_id: ConnectionId = ctx.connection_id;
// 时间戳
let timestamp: Timestamp = ctx.timestamp;
}🔔 生命周期 Reducer
// 客户端连接时调用
#[spacetimedb::reducer(client_connected)]
pub fn on_connect(ctx: &ReducerContext) {
// 新用户加入逻辑
}
// 客户端断开时调用
#[spacetimedb::reducer(client_disconnected)]
pub fn on_disconnect(ctx: &ReducerContext) {
// 用户离开逻辑
}