# 工作区（Workspace）

工作区是 vjmap 的**命名空间机制**：不同工作区下的**地图数据**互相隔离（独立存储目录与图形子进程）。注意：**KV 存储与符号库是全局的，不按工作区隔离**；全文索引靠 `workspace` 字段区分。

## 1. 概念

- **默认工作区**：不带名字；URL 用 `/api/v1/map/...` 前缀
- **命名工作区**：人为创建；URL 变为 `/api/v1/workspace/{name}/...` 前缀
- 工作区本身也有状态：`{name, alias, isPublic, workDir, idleCloseTime, disableFullSearch, createTime}`，由 `/api/v1/service/getWorkspace` 列出（裸 JSON 数组，非 `{code,msg,data}` 信封）
- 一个 token 理论上可访问所有工作区；实际权限由 `AuthorityId` 决定

## 2. 切换工作区（SDK）

### Python

```python
svc = Vjmap("http://127.0.0.1:27660/api/v1", token)
svc.switch_workspace("team_a")          # 之后所有 map_url / cmd_url 都会自动带上 /workspace/team_a
svc.open_map("finance", "v1", mapopenway="Memory")  # → /api/v1/workspace/team_a/openmap/finance?version=v1
svc.switch_workspace("")                # 切回默认工作区
```

### Node

```javascript
svc.switchWorkspace('team_a');
await svc.openMap({ mapid: 'finance', version: 'v1', mapopenway: 'Memory' });
svc.switchWorkspace('');
```

## 3. 生命周期接口

| # | 操作 | URL | 方法 |
|---|------|------|------|
| 1 | 列出 | `/api/v1/service/getWorkspace` | GET |
| 2 | 创建 | `/api/v1/service/workspaceCreate` | POST |
| 3 | 修改 | `/api/v1/service/workspaceModify` | POST |
| 4 | 删除 | `/api/v1/service/workspaceDelete/{name}` | DELETE |
| 5 | 状态 | `/api/v1/service/workspaceStatus` | GET |

详细字段、响应示例请看 [`api/07-workspace.md`](api/07-workspace.md) 。

## 4. 底层隔离机制

- **每个命名工作区对应一个独立的图形服务子进程**（独享端口，懒启动 `CreateMapProcIfIsNull`，被删后不再拉起）。网关注册 `/api/v1/workspace/{name}/*action` → 反代到该区子进程端口，**前缀剥掉**（子进程收到 `/cmd/...`、`/tile/...` 等裸路径），因此存储天然物理隔离
- 默认工作区同理：`/api/v1/map/*action` 剥前缀后反代到主图形服务进程
- 因此凡是 `/api/v1/map/` 下的路径都能在 `/workspace/{name}/` 下一模一样使用
- `/api/v1/service/*`（KV、符号库、全文搜索等）**不受**工作区前缀影响。其中只有**全文搜索**接受 `workspace=` 参数做隔离（Document 的 `workspace` 字段）；KV（`data/`、`datas`、`datakeys`）与符号库（`symbol/*`）源码中**没有** workspace 参数，是全局共享的——多工作区部署时用 key 前缀自行区分

## 5 反模式

- 不要在**热路径**里频繁调用 `switch_workspace()` 再立刻发请求；SDK 内部只是改前缀，没 IO，但业务代码可能会混乱。建议**一个 svc 实例绑一个 workspace**。
- 不要把 `workspace` 和 `mapid` 拼到一起当复合键用；保持**每图一个 mapid，workspace 单独字段**。
