只要出现下面**任一信号**,就必须遵守 ES 的“异步契约”——用 `ActionListener` 把结果/异常转成回调,而**不是 `return`/`throw`**:
---
### 1. 框架强制签名
- 方法返回 `void`,最后一个参数是 `ActionListener<XXX>`
例:`TransportSearchAction#execute(Request, ActionListener<SearchResponse>)`
- **编译器不会让你 `return` 或 `throw`,只能回调**。
---
### 2. 可能跨线程 / 跨节点
- 逻辑里出现 **Netty 网络调用**、**线程池提交**、**远程 RPC**
→ 结果不知何时、在哪个线程回来,**必须回调**。
- 例:搜索要 scatter 到各分片 → gather,**不能阻塞 Netty 线程**。
---
### 3. 需要链式组合
- 想继续 `.map()` / `.delegateFailure()` / `.whenComplete()` 拼接后续步骤
→ 只有 `ActionListener` 才提供这些链式 API。
- 例:先 `search` 再 `scroll` 再 `deleteByQuery`,**链式比嵌套 try-catch 清爽**。
---
### 4. 需要统一异常策略
- 团队规定:**所有异常必须走 `onFailure`,最外层统一日志/指标/降级**
→ 用 `completeWith` / `wrap` 可以保证**任何检查型异常都被转成回调**,不会漏到线程最外层。
---
### 5. 同步块但想“零 try-catch”
- 一段**纯本地同步代码**(如 `internalRecoverFromStore`),
却想**省掉手写 try-catch**,同时保留**异步签名**供上层链式扩展
→ 用 `completeWith` 包一层即可**同步执行、回调出口**。
---
### 一句话信号
> **只要方法签名出现 `ActionListener<XXX>`,或者逻辑里可能跨线程/网络,就立刻遵守 ES 异步契约:**
> **“成功 → onResponse,失败 → onFailure”,绝不 `return`/`throw`。**


被折叠的 条评论
为什么被折叠?



