# `order_case` 示例说明

这个示例现在保留两件事：

1. 多层错误体系与跨层转换
2. 当前已落地的消费协议

也就是说，它不是一个“最短 hello world”，而是一个“复杂度受控，但仍能看出分层价值”的示例。

## 这个示例展示什么

示例里保留了四层错误语义：

- `ParseReason`
- `UserReason`
- `StoreReason`
- `OrderReason`

对应一条短业务链：

1. `parse order`
2. `load user`
3. `check balance`
4. `save order`

其中：

- 解析层返回 `StructError<ParseReason>`
- 用户层返回 `StructError<UserReason>`
- 存储层返回 `StructError<StoreReason>`
- 服务层最终收敛成 `StructError<OrderReason>`

## 这个示例的核心价值

### 1. 结构化错误第一次进入体系

存储层对 `std::io::Error` 使用：

```rust
persist_order(...)
    .into_as(UvsReason::system_error(), "write order record failed")
```

这展示的是“普通错误第一次进入结构化体系”的主路径。

### 2. 跨层 reason 收敛

服务层把子层错误往上收敛时，使用：

```rust
.doing("parse order")
.with_context(&ctx)
.err_conv()?
```

这展示的是：

- 下层保留自己的局部 reason
- 上层通过 `From<R1> for R2` 做 reason 收敛
- context/path 继续向上保留

### 3. 最终只暴露上层领域错误

对调用者来说，最终只接触：

```rust
Result<T, StructError<OrderReason>>
```

这比直接把所有底层 reason 暴露给上层更符合分层边界。

### 4. 消费协议

每个失败场景最后都会直接展示一组“摘要优先”的结果：

- `identity_snapshot()`
- `exposure_snapshot(...).decision`
- `http_response(...)`
- `render_user_debug(...)`

这个示例最终选择 `render_user_debug(...)` 作为“给人读”的默认展示出口，而不是直接把
`Debug` 结构体或完整 verbose report 打出来。

这说明多层错误体系和消费协议不是二选一，而是可以叠加的：

- 运行时传播时保留结构化层次
- 出口消费时统一走稳定协议

## 推荐关注点

### 入口上下文

入口上下文统一写在服务层：

```rust
let mut ctx = OperationContext::doing("place_order");
ctx.record_field("user_id", user_id.to_string());
ctx.record_field("order.raw", raw_order);
ctx.record_meta("component.name", "order_service");
```

它展示的是：

- `record_field(...)` 适合展示型 field
- `record_meta(...)` 适合结构化 metadata

最终摘要输出大致会收敛成：

```text
code          : biz.order_invalid (Biz)
detail        : order text must not be empty
http          : 400 Public retryable=false
path          : place_order / parse order
context       : user_id="42", order.raw=""
component     : order_service
```

### `From` 映射的边界意义

示例里保留了：

- `From<ParseReason> for OrderReason`
- `From<UserReason> for OrderReason`
- `From<StoreReason> for OrderReason`

这不是为了写样板代码，而是为了明确：

- 子层 reason 可以更细
- 上层领域 reason 可以更稳

### `StorageFull` 的例子

这个例子把存储层边界收得更清楚：

- `write_impl(...) -> std::io::Error`
- `persist_order(...) -> StoreError`
- `save_order(...) / place_order(...) -> OrderError`

它表达的是：

- 原始 I/O 只存在于更底层 helper
- 存储层公开边界直接返回 `StoreError`
- 服务层再通过 `err_conv()` 把 `StoreError` 收敛成 `OrderError`

## 为什么不再用更复杂的老版本写法

旧版本示例的问题是层次很多，但阅读负担太大，容易把注意力都耗在样板代码上。

当前版本的取舍是：

- 保留多层 reason 和转换
- 缩短每层逻辑
- 直接把重点落在“分层传播 + 协议消费”上

## 如果你只想运行

```bash
cargo run --example order_case
```

如果你想看协议本身的正式说明，直接看：

- `docs/protocol-contract.md`
