Files
baozaotumao 39fe248f9f feat: 重组为标准 skill 包结构 + 修复 verify.sh bash 3.2 兼容
- 新增 .claude/skills/new-project/SKILL.md(标准 skill 格式)
- install-skill.sh 安装时组装 SKILL.md + verify.sh,单一源无重复
- verify.sh 改用索引数组替代 declare -A,兼容 macOS bash 3.2
- log_pass/log_skip 显式 return 0,避免 set -e 下非 verbose 误退出
- README 改为 skill 优先;补全 copier.yml/scripts/template 入库
2026-06-01 21:19:45 -07:00

48 lines
2.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
paths: ["backend/**"]
---
# backend-concurrency
Backend 并发模型:WebSocket 双向转发的 Task 管理 + SQLite 并发处理。
Backend 是纯异步 I/O 代理,无 CPU 密集工作,无需进程池。关注点在两处:双向转发的任务管理、SQLite 并发。
## 1. WebSocket 双向转发
每个连接 = 两个 Task(上行 / 下行),并联运行;任一侧断开必须取消另一侧,避免 Task 泄漏:
```python
@router.websocket("/ws/{session_id}")
async def ws_proxy(ws: WebSocket, session_id: str, repo: SessionRepository = Depends(get_session_repo)):
await ws.accept()
await session_service.get_or_create(repo, session_id)
checkpoint = await session_service.load_checkpoint(repo, session_id)
async with agent_client.connect(session_id, checkpoint=checkpoint) as agent_ws:
to_agent = asyncio.create_task(forward_to_agent(ws, agent_ws))
to_browser = asyncio.create_task(forward_to_browser(agent_ws, ws, repo)) # 转发同时写 checkpoint
done, pending = await asyncio.wait(
{to_agent, to_browser}, return_when=asyncio.FIRST_COMPLETED
)
for task in pending: # 一侧结束,取消另一侧
task.cancel()
```
## 2. SQLite 并发
SQLite 默认串行写,并发下易触发 `database is locked`。引擎连接时必须开 WAL + busy_timeout
```python
# db/base.py —— connect 时执行
@event.listens_for(engine.sync_engine, "connect")
def set_sqlite_pragma(dbapi_conn, _):
cursor = dbapi_conn.cursor()
cursor.execute("PRAGMA journal_mode=WAL") # 读写不互斥
cursor.execute("PRAGMA busy_timeout=5000") # 锁等待 5s 而非立即报错
cursor.execute("PRAGMA foreign_keys=ON")
cursor.close()
```
- 一个请求/连接一个 `AsyncSession``get_db` 作用域),**禁止跨 Task 共享 Session**
- 本工作负载写入量低,WAL 足够;若未来高并发,迁移到 Postgres(仅换 `database_url` 与 driverORM 不变)