Supabase:先在分支里试改,再决定怎样带回线上
Supabase为应用提供Postgres数据库、数据接口及配套后端服务。分支让团队在独立环境中尝试结构变化,检查测试结果与迁移差异,再决定是否合并到正式项目。
先尝试拆解问题、设计和实现,再展开思路,检查状态、边界与取舍,并设计验证用例。思路提供分析路径,不给出完整实现。
01
代码思考进阶
部署步骤现在可以开始,还是被上游失败阻断?
练习场景
部署预览环境要先检查服务健康,再应用结构迁移,然后导入测试记录。设计一个纯内存依赖分析器,告诉界面哪些待执行步骤现在可开始、哪些在等待、哪些被失败阻断。它不执行迁移、不发网络请求,也不自动重试。下面是自拟协议,不是 Supabase 内部调度器的实现。
输入与规则
- steps 最多 100,000 项,每项是非 null 对象,含唯一非空字符串 id,以及 state:pending、running、succeeded、failed 四者之一。空数组合法。输入只读,只校验题面列出的字段;所有出现的 ID 字符总长度为 L。
- dependencies 最多 300,000 项,每项是非 null 对象,含非空字符串 before 与 after,表示 before 成功后 after 才能开始。两端必须存在。重复的同向边忽略,不重复计入依赖;自环和任何有向环使整批输入非法。
- 这是一个固定的、无重试的运行快照。running、succeeded 或 failed 都表示该步骤已经开始过,其所有直接前置步骤必须处于 succeeded;不满足则快照非法。状态不会在分析过程中改变。
- 对每个 pending 步骤:只要任意上游祖先 failed,结果就是 blocked;否则,所有直接前置均 succeeded 时为 ready(无前置也满足);其余为 waiting。failed 是某步骤的运行状态,blocked 是尚未开始的步骤因上游失败而无法推进的分析结果。
- 输出所有 pending 步骤的 id 与分类,保持 steps 输入顺序。不输出已开始步骤,不选择唯一失败祖先,也不列出全部祖先。任何结构、字段或快照错误都返回带位置的错误,不返回部分分类;无需列举全部错误,但必须区分非法输入与合法 waiting。
小例子
steps 顺序为 A健康检查 succeeded、B迁移 failed、C测试数据 pending、D函数检查 pending、E配置检查 pending、F独立检查 pending。依赖是 A→B、B→C、B→D、A→E。请写出 C、D、E、F 的结果。
再分别修改:(a) B 改为 running;(b) 加入 C→A;(c) C 改为 succeeded;(d) 将 A→B 重复发送一次。说明哪些仍有合法分类,哪些必须拒绝,以及理由。
交付物
说明输入校验、去重、判环、失败传播与原顺序输出的方案。要求避免为每个步骤遍历全部祖先,避免深链递归导致调用栈溢出。用 n 个步骤、m 条输入边和 L 分析时间空间,至少列出四个不变量;可以讨论 JS Map 或 Rust 集合,不写完整实现或逐行伪代码。
查看思路
- 先建立身份与依赖。 ID 索引保留输入位置,检查字段与端点,再以结构化双层索引去重边,避免拼接字符串碰撞。空图正常,非法端点不能变成隐含节点。
- 用迭代拓扑遍历识别环。 统计去重后的入度,用队列处理零入度节点。处理数少于 n 说明有环;先确认整图合法,再交付分类,不能先把可达的半张图当成功结果。
- 核对已开始步骤的前置状态。 running、succeeded、failed 都必须有全部直接前置 succeeded。该题禁止重试和快照内变化,因此不能用“前置后来失败”解释不一致输入。
- 沿依赖传播一个失败标记。 节点汇总上游是否失败,再把自己的 failed 状态一起传给后继。不保存所有祖先集合。pending 有失败上游即 blocked;否则检查直接前置是否全成功,区分 ready 与 waiting。最后按原步骤顺序收集。
- 推演并验证成本。 主例 C/D blocked、E/F ready;a 中 C/D waiting、E/F ready;b 有环拒绝;c 在 B failed 时 C 已成功,快照非法;d 重复边不改结果。输入重排只改输出顺序,重复边不改分类,阻断可跨多层传播,任何错误无部分输出。平均哈希操作下 O(n+m) 集合/图操作,另计 L 字符成本;索引、去重边、队列和输出空间可界定为 O(n+m+L)。不能为每个节点复制其全部祖先。