跳转到内容
use-cases / a-progress-bar-your-boss-can-spectate / hero
PIPE · ?PROGRESS · SSE

老板可以围观但无需加入的进度条

你在跑一次八小时的迁移。五个人想知道状态,但又不想占用接收槽或打断数据流。在 pipe URL 后追加 ?progress。任何打开它的人都能看到一个实时 HTML 仪表盘——已传输字节、当前速度、ETA、状态切换。无论多少双眼睛在看,迁移都以全速运行。

阅读 pipe progress 文档
use-cases / a-progress-bar-your-boss-can-spectate / mechanism

一个查询参数如何变成实时仪表盘

?progress 是对 pipe 路径的另一次独立读取,它监听传输状态而不占用接收槽。迁移察觉不到它。浏览器看到的是 HTML 仪表盘;curl 看到的是干净的 SSE 流。

SPECTATOR TIMELINEZERO RECEIVER SLOTS
T+0 min
BOSS OPENS URL

She pastes the pipe URL with ?progress into her phone browser. The HTML dashboard appears instantly — state: waiting, 0% — no install, no login, no receiver slot consumed.

T+22 min
STREAM IS LIVE

SSE pushes a state: streaming event. The progress bar snaps to 22%, bytes tick up, MB/s settles at 118. The dashboard updates itself every 250 ms without a single page reload.

T+4 h
BOSS GOES TO BED

She closes the tab. Her spectator connection drops. The migration doesn't notice — it was never in the data path. The sender and its one real receiver carry on.

T+8 h
WAKES TO 100%

She reopens the URL at sunrise. The dashboard shows a done event: 7.6 GB transferred, 8h 2m, no errors. Server-side state survives the refresh — latecomers always see the final line.

T+8h 4m
SENDS THE ACK

She forwards the URL to the team Slack. Three engineers open it and see the same done state. No status thread to close, no Grafana panel to un-star. One URL, five witnesses, zero interruptions.

spectate.sh
# 1. Sender — eight-hour migration. Same as always.
tar czf - /var/lib/postgres | curl -T - "$PIPE/api/v1/pipe/migration"

# 2. Receiver — the only client that matters for backpressure.
curl "$PIPE/api/v1/pipe/migration" | tar xzf - -C /restore

# 3. Boss opens the URL on her phone. HTML dashboard. No setup.
# => https://pipe.hoody.com/api/v1/pipe/migration?progress

# 4. You want SSE for a Slack bot? Same URL, different Accept.
curl -N -H "Accept: text/event-stream" \
  "$PIPE/api/v1/pipe/migration?progress" \
  | grep -E '^event: (progress|state|done)'
# event: state    \n data: ["state":"streaming","receivers":1]
# event: progress \n data: ["bytes":5046464512,"mbps":118,"etaSec":840]
# event: done     \n data: ["bytes":8160000000,"durationSec":28800]

三种 SSE 事件类型。state 用于状态切换(idle → waiting → streaming → complete),progress 在字节流动时每 250ms 推送一次(bytesTransferred、speed、ETA),done 在结束时推送一次最终统计。每条路径最多五十名旁观者,连接 TTL 三十分钟,传输后保留三十秒以便后到的人看到成功的那一行。

use-cases / a-progress-bar-your-boss-can-spectate / audience

三种受众,一个 URL

同一个 ?progress 端点服务于浏览器标签页、curl 管道和后台轮询的状态页。它们都不会拖慢传输。

use-cases / a-progress-bar-your-boss-can-spectate / punchline

围观迁移本身就是一个 URL。迁移察觉不到。

0 个接收槽被占用每条路径最多 50 名旁观者
迁移1 个发送方、1 个接收方、满带宽
旁观者12 双老板的眼睛盯着仪表盘,0 背压
  • 无需照看 Slack 频道
  • 无需接 Grafana 仪表盘
  • 无需自写进度端点
use-cases / a-progress-bar-your-boss-can-spectate / replaces

这取代了什么

每个团队都有一种回答“进度到哪了?”的方式。这些方式里,大部分都需要运行一个服务、接一个仪表盘、或照看一个聊天频道。在 pipe URL 上加一个查询参数则不需要其中任何一项。

  • Slack #migrations 频道更新一个人每五分钟敲一次百分比
  • Grafana 仪表盘一个 exporter、一个 Prometheus 抓取、一个要维护的面板
  • 自定义进度端点定制路由、定制 schema、定制保留期 bug
  • 通过 SSH 共享 Tmux为了看一个数字往上跳还要堡垒机访问权限
  • Datadog 指标面板为一次传输支付每主机 agent 和每指标价格
  • 「到了没?」催问五个队友在不同线程里问同一个问题
use-cases / a-progress-bar-your-boss-can-spectate / cta

发出 URL。停止发送状态更新。

阅读 pipe API 指南
use-cases / a-progress-bar-your-boss-can-spectate / related

阅读其他内容