# FlowGate 新手指南

3 分钟上手并发门控。

## 安装

```bash
moon add flowgate
```

## 一分钟快速开始

```moonbit
// 1. 导入
// 在你的 moon.pkg 中添加 "flowgate/lib"

// 2. 创建门控（默认：全局100/每键10/每会话5）
let gate = @flowgate.default_gate()

// 3. 申请槽位
match gate.acquire("my-tool", "user-123") {
  Ok(msg) => {
    // 执行业务...
    println("got slot: " + msg)
    // 4. 用完释放
    gate.release("my-tool", "user-123")
  }
  Err(e) => println(e)  // 被拒绝或排队
}
```

## 常用场景

### 场景1：保护下游 API

```moonbit
// 限制同时并发调用外部 API 不超过 50
let api_gate = @flowgate.new_builder()
  .global(50)          // 最多 50 个并发请求
  .queue_size(100)     // 100 个请求排队等待
  .on_block(fn(reason) { metrics.inc("api_throttled") })
  .build()
```

### 场景2：多租户隔离

```moonbit
// 每个租户最多 3 个并发任务
let tenant_gate = @flowgate.new_builder()
  .per_session(3)     // 每个 session = 一个租户
  .queue_size(0)      // 不排队，满了直接拒绝
  .build()
```

### 场景3：三种预设

```moonbit
let dev  = @flowgate.permissive_gate()  // 500/50/20 开发环境
let prod = @flowgate.default_gate()     // 100/10/5  生产环境
let safe = @flowgate.strict_gate()      // 50/3/2    保守模式
```

## 核心概念

| 概念 | 说明 |
|------|------|
| **全局上限** | 所有请求的并发总数 |
| **键上限** | 每个 key（如工具ID）的并发数 |
| **会话上限** | 每个 session（如用户）的并发数 |
| **队列** | 满了之后的等待队列，容量可配 |
| **事件钩子** | on_block / on_acquire / on_release 三个回调 |

## 从 AegisRun limiter 迁移

如果你在用 AegisRun 的 `limiter.mbt`：

```moonbit
// 之前（AegisRun 内嵌）
let lim = @aegisrun.lib.default_limiter()
lim.acquire("tool", "session")

// 之后（FlowGate 独立库）
let gate = @flowgate.default_gate()
gate.acquire("tool", "session")
```

## 常见问题

**Q: 队列和拒绝有什么区别？**
A: `queue_size > 0` 时，超出上限的请求进入队列（Err 含 "QUEUED"）。`queue_size = 0` 时直接拒绝（Err 含 "REJECTED"）。

**Q: 如何知道还有多少槽位？**
A: `gate.available()` 返回剩余数，`gate.is_full()` 返回是否满。

**Q: 事件钩子有什么用？**
A: 埋点监控。例如 `on_block` 里发告警，`on_acquire` 里记日志。

## 下一步

- [README](README.md) — API 完整参考
- [LICENSE](LICENSE) — Apache-2.0
