题目重点:拆解解析版本、规划DAG、验证下载与原子激活,解释拓扑排序不能解决全部依赖冲突。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练输入包manifest有name/version/dependencies/artifact digest,单环境每包选一版本;这些字段是教学schema,原题待核。
- payload作为调用者数据传给显式install handler,传递范围/权限/可序列化格式需确认;不把任意字符串自动拼shell。
- 本文无嵌入未运行安装代码,设计状态与不变量可独立验收,实际安全/事务由目标环境实现。
解题路线
- 先分两个问题:选择相容版本与在已解析图上排序。name相同约束可能冲突,拓扑排序只处理依赖先后/环,不能解版本不相容。解析成功产生固定版本/digest lock plan,之后下载/执行不偷偷换最新版。
- 固定图按dependent→dependency描述时,执行顺序要保证每个dependency先完成;拓扑算法的边方向/入度先明确,不能用代码形式让顺序反了。缺包/循环报告依赖见证,多个根共享依赖只安装一次。
- 分阶段resolve→fetch→verify→stage→activate→commit,状态按包版本/digest和attempt ID记录。并发下载可先做,执行依赖约束不能因下载快就先运行dependent。失败时保留可恢复记录,不能把half-installed当成功。
- payload绑定目标包/版本/请求ID、schema与最小权限,普通对象传递比拼接命令安全;记录不泄露敏感内容。重试install handler必须定义幂等键/副作用,操作系统/外部数据库副作用不天然可rollback。
- 原子激活可用版本目录与指针切换,再按平台合同fsync/锁;已安装依赖可能被其他包共用,回滚不能一律删除全部依赖。引用计数/环境快照和旧版本保留政策需明确。
- 验收包括相容版本冲突、环、digest错、网络断、激活时宕机、重复请求与共享依赖。真实pip解析有backtracking,官方参考https://pip.pypa.io/en/stable/topics/dependency-resolution/;本文并非声称原题指定pip。
手动走一遍
A依赖B<2、C依赖B≥2;单环境只装一个B则无解,即使A/C/B图无环。若解析为A→B→D与C→D,先D,再B/C,最后A;D只安装一次。A handler已向外部服务写入后本地失败,重试需要业务幂等或补偿,目录rollback不能撤掉那次网络副作用。
规模与取舍
已解析DAG拓扑O(V+E),版本选择是另一约束搜索,可能回溯,不能统称线性。下载量按artifact总bytes、执行按脚本成本,状态/缓存按包版本保留增长。
易错点与追问
容易失分的边界
- 拓扑排序解决全部版本冲突。
- 边方向弄反。
- 下载完先执行忽略依赖。
- payload拼shell。
- 失败回滚删除共享依赖。
- 外部副作用天然事务。
继续深挖
- 怎样报告最小冲突约束?
- 并发安装共享依赖怎么加锁?
- payload重试如何幂等?
- 安装完成但ack丢失怎样恢复?
技术参考
- pip Dependency Resolution 官方文档:公开机制参考;原面试具体版本/实现未知,文章已限定教学范围。
