Moveet:事件、录制与回放、icon rail UI,以及 500 多个测试

发布: (2026年3月16日 GMT+8 18:38)
7 分钟阅读
原文: Dev.to

Source: Dev.to

What shipped

🚦 Fleet management

车辆现在可以被分组为 具名、颜色编码的车队。您可以创建车队、将车辆分配到车队中,界面会根据车队为路线和标记着色——这对于模拟多个运营商共享同一道路网络非常方便。

REST API

POST   /fleets
GET    /fleets
DELETE /fleets/:id
POST   /fleets/:id/assign
POST   /fleets/:id/unassign

WebSocket events

  • fleet:created
  • fleet:deleted
  • fleet:assigned

⚠️ Incidents and dynamic rerouting

在网络的任意位置投放道路事故。所有当前正通过受影响路段的车辆都会实时重新规划路径——A* 会从车辆的当前位置重新计算,绕过被封锁的边。

REST API

POST   /incidents          # create incident, triggers rerouting
GET    /incidents          # list active incidents
DELETE /incidents/:id      # clear it, vehicles return to normal paths
POST   /incidents/random   # random incident for testing

WebSocket event

  • vehicle:rerouted – 为每一辆被重新规划路径的车辆触发

事故标记会显示在地图上。


🎬 Session recording and replay

每个仿真会话都可以记录为带时间戳的 NDJSON 文件。文件格式为一行标题,随后每行一个事件(方向指派、车辆快照、事故等)。

REST API

POST   /recording/start
POST   /recording/stop
GET    /recordings

Replay control API

POST   /replay/start    { "file": "path/to/recording.ndjson" }
POST   /replay/pause
POST   /replay/resume
POST   /replay/stop
POST   /replay/seek     { "timestamp": 12000 }
POST   /replay/speed    { "speed": 2 }
GET    /replay/status

回放支持 1×、2×、4× 速度。UI 显示一个插值进度条,在服务器 tick 之间平滑前进,避免每 500 ms 的跳动。


🖥 UI redesign – icon rail + panel sidebar

旧的浮动覆盖层已被左侧边缘的 图标轨道 取代——一条垂直的图标按钮条,每个按钮切换一个面板。

IconPanel
🚗Vehicles – 列表、过滤、选择
🗂Fleets – 创建、分配、颜色
⚠️Incidents – 带徽章计数的活动列表
Recordings – 开始/停止/浏览/回放
👁Visibility – 切换地图图层
Speed – 仿真速度控制
⚙️Adapter – 热插拔源/汇插件

底部停靠栏保存实时仿真控制(播放/停止/重置/录制),在回放时会折叠为回放传输条。

所有面板组件均基于共享的原语集(PanelShellPanelHeaderPanelSection)和统一的主题令牌集合构建,因而每个面板外观一致,无需为单个组件单独写样式。


✅ Test coverage – from 410 to 502 tests

仿真器的测试套件显著增长。新增文件如下:

FileWhat it covers
rateLimiter.test.ts窗口限制、429 响应、按 IP 追踪、清理间隔
helpers.test.tscalculateBearinginterpolatePositioncalculateDistancenonCircularRouteEdgesestimateRouteDuration
serializer.test.ts包含或不包含车队分配的 serializeVehicle
config.test.tsverifyConfig – 缺失文件、端口范围、速度顺序、所有数值约束
SimulationController.test.ts完整生命周期:startstopgetStatussetOptionsgetVehiclesgetInterval,以及所有回放方法

值得注意的测试模式SimulationController 测试会 stub VehicleManager.prototype.setRandomDestination,以防在小型测试网络 fixture 上调用 A*,随后再恢复。回放测试在每个测试之前向临时目录写入最小的 NDJSON 文件,所有资源在 afterEach 中清理。


📡 WebSocket – 100 ms batching + back‑pressure

车辆位置更新现在 每 100 ms 批量发送一次,在发送前进行合并,以降低带宽占用并提供后压机制,确保在高负载情况下客户端不会被淹没。

adcast. 如果客户端的写缓冲区被堵塞,广播器会跳过该客户端,而不是让队列无限增长。这使得模拟器在 50–100 辆车辆的情况下仍能保持可用,且不会出现连接退化。

所有广播事件类型

vehicles          – batched position array (100 ms window)
status            – simulation state (running / ready / interval)
options           – current StartOptions
heatzones         – HeatZoneFeature[]
direction         – active dispatch assignment
waypoint:reached  – vehicle reached a waypoint
route:completed   – vehicle completed its full route
reset             – simulation was reset
fleet:created / fleet:deleted / fleet:assigned
incident:created / incident:cleared
vehicle:rerouted  – live A* reroute triggered

🔧 CI 改进

GitHub Actions 工作流之前在并行的三个作业中各运行一次 npm ci(每个作业一次)。现在它有一个专门的 setup 作业,只安装一次并根据 package-lock.jsonnode_modules 进行缓存。Lint、测试和构建作业从该缓存恢复。构建作业还会使用每次提交的键以及分支级别的恢复键来缓存 .turbo/


架构图(已更新)

┌──────────────────────────────────────┐
│  apps/ui                             │
│  React 19 · D3 7 · Vite · TS 5.8    │
│  Mercator SVG map, 1×–15× zoom       │
│  Icon rail · Panel sidebar · Dock    │
└──────────────┬───────────────────────┘

架构概览

               │ REST + WebSocket

┌──────────────────────────────────────┐
│  apps/simulator                      │
│  Express 4 · ws 8 · Turf.js 7       │
│  GeoJSON graph · A* · LRU cache      │
│  WS broadcaster · 100ms batching     │
└──────────────┬───────────────────────┘
               │ GET /vehicles · POST /sync

┌──────────────────────────────────────┐
│  apps/adapter (optional)             │
│  Source plugins: static / graphql /  │
│  rest / mysql / postgres             │
│  Sink plugins: console / graphql /    │
│  rest / redpanda / redis / webhook   │
└──────────────────────────────────────┘

快速开始

curl -O https://raw.githubusercontent.com/ivannovazzi/moveet/main/docker-compose.ghcr.yml
docker compose -f docker-compose.ghcr.yml up

打开 . 无需配置,也不需要 API 密钥。

仓库:


欢迎在评论中提出关于 A 实现、D3 渲染器或录制格式的任何问题。*

0 浏览
Back to Blog

相关文章

阅读更多 »

Meta 不再放弃 Jemalloc

- Meta 认识到 jemalloc 作为高性能内存分配器在其软件基础设施中的长期收益。 - 我们正在重新聚焦 jemalloc,……