排查前可以采集"事发任务"的如下关键字段: taskId、fileId、目标type、源文件大小 / URL、status、message、最近一次progress、首次创建时间等,以方便后续问题定位。
status != 0/v2/import 或 /export/{fileId},HTTP 200,但响应 status 不是 0,data 是 null。type 不在支持列表里)、签名 / token 失效、fileId 已存在且关联了别的协同文件、源文件无法访问。message:石墨在这里通常会给出可读的原因。type 是否在指南的"导入 / 导出支持格式表"内。X-Shimo-Signature 与 X-Shimo-Token 是否仍在有效期内,时钟是否同步。curl -I "${fileUrl}" 验证石墨能否拉到源文件。message 处理对应一项,并在业务库里把这条记录直接打 failed,不要进入轮询。重试前换一个新的 fileId,不要复用。fileId 冲突status != 0,message 提示文件已存在或类型不匹配。fileId 已经关联到某个石墨协同文件(可能是上次半成功的导入,也可能被另外的业务流程用过)。石墨不支持对已存在的 fileId 做覆盖式导入。fileId,看它是不是上一次失败任务残留的 importing 记录。importing:标记为 abandoned,重新生成 fileId 再发起导入。fileId 用 UUID / Snowflake 这类全局唯一方案;不要把"原始文件名"或"用户 ID + 时间戳秒级"作为 fileId。fileUrl 拉取失败status != 0,message 指向下载错误;或任务接受了但轮询很快变成失败。fileUrl:内网地址、未签名的对象存储私链、CDN 防盗链拦截、源文件已被删除等。curl -I "${fileUrl}" 模拟石墨服务端拉取,看 HTTP 状态码。status != 0。石墨文档明确写了"不支持导入 0kb 文件"。fileUrl 之前先校验文件大小 > 0;前端展示"文件为空"提示,不要把空文件传到石墨。status != 0,message 提示文件类型不支持。.rtf 走 document 通道、把 .numbers 走 spreadsheet 通道。status: 0 就当成功/v2/import 与 /export/{fileId} 是任务创建接口,status: 0 只代表"任务被石墨接收",文件还在转换中。progress == 100 才算业务上的成功。前端展示一定要分"导入中 / 导入成功"两态,不要合并。fileId,看到空文档或编辑器报"文件不存在 / 权限错误"。fileId 在石墨侧还没有内容;如果你的应用前端立刻打开它,编辑器要么拿到空内容、要么连协同会话都建不起来。importing → 轮询完成 → ready"切换状态,前端只在 ready 才允许进入编辑器;中间态展示"导入中"占位页。progress 在 70-90 区间晃悠,过了 10 分钟还没到 100。failed。重试时新建任务而不是继续轮询旧 taskId。progress 卡在某个值(例如 35),持续 30 分钟以上不变。taskId)。downloadUrl 已过期downloadUrl,业务侧晚了几分钟才去下载,结果 403 / 404。downloadUrl 是临时签名链接,有效期仅 5 分钟。downloadUrl 后立刻消费——后端在同一次轮询完成的处理函数里下载并转存到自己的对象存储。如果一定要延后下载,需要在 5 分钟内重新调进度接口(同一个 taskId 仍有效)拿新的 URL,而不是把旧 URL 再用一次。downloadUrl 直接返回前端downloadUrl 后立刻下载文件流,转存到自己的对象存储(OSS / S3 / COS …)。downloadUrl 并代理流给前端。downloadUrl 留在内存或前端 state,没落到自己的对象存储。taskId 当业务幂等键taskId、3 份导出文件。taskId 由石墨生成,每次调用创建接口都会得到新值。用它做去重,永远去不掉。fileId + type + 触发时间窗),在调石墨之前先查表:exporting / ready 的同键任务,直接返回那个 taskId 给用户。taskId 与状态。importing 或 exporting 的记录,用户列表里看到"导入中"几十分钟没动静。failed;或者代码里只处理了"成功"分支,"失败"路径漏写。ready 或 failed)。importing / exporting"的记录,按 B.4 / B.5 的逻辑判定失败。taskIdmessage,没把 taskId / fileId / type / fileUrl / 时间 这些定位字段一起持久化。taskId / fileId / 目标 type / 源文件大小 / 源文件 URL(脱敏)/ 最近一次 status & message / 重试次数 / 时间 戳。这套字段也方便你在排查时拿去找石墨支持。| 检查项 | 验证方式 |
|---|---|
| 轮询有总超时 | 模拟一个永不完成的任务,确认 N 分钟后业务侧自动落 failed |
| 轮询间隔 ≥ 3s 且指数退避 | 抓包看一次完整轮询的间隔序列 |
downloadUrl 在 5 分钟内被消费 | 看导出日志,从拿到 URL 到下载完成的时间戳差 < 5min |
| 导出文件落到自家对象存储 | 业务库存的是对象存储路径,不是石墨临时 URL |
| 业务侧幂等键去重 | 连续点 3 次同样的导出按钮,最终只产生 1 个有效任务 |
| 0kb / 不支持格式 / 过大文件被前端拦截 | 用极端样本走一遍流程 |
| 失败日志含完整上下文 | 日志样本里有 taskId / fileId / type / message |
| 任务长跑监控 | 有看板或告警跟踪"importing / exporting 超过 N 分钟"的记录数 |
重试时使用新 fileId / 新 taskId | 失败重试不是简单复用旧任务 |