首页/新闻资讯/正文详情

Plannotator PR 上下文预热缓存:用会话级 Promise 缓存消除 Overview 加载闪烁

发布时间:2026/9/25 12:25:52 来源:云帆数科 栏目:资讯中心
Plannotator PR 上下文预热缓存:用会话级 Promise 缓存消除 Overview 加载闪烁
【免费下载链接】plannotatorAnnotate and review coding agent plans and code diffs visually, share with your team, send feedback to agents with one click.项目地址https://gitcode.com/gh_mirrors/pl/plannotator点击查看免费下载导读本文围绕 Plannotator 仓库中的技术决策文档 synthesis-pr-context-warm-cache-20260630-110258.md 展开讲解如何通过纯服务器端、最小改动的方式为 PR 审查服务器的 Overview 面板预取上下文数据PR 描述、评论、审查线程、CI 检查、标签、合并状态、关联 Issue从而让面板打开时通常能直接命中已就绪的数据而不是等待一次全新的慢速 Provider 调用。读完本文你将掌握detached but owned脱离但拥有的 Promise 缓存设计范式、失败驱逐策略、预热与端点调用的三处接线方式以及它在两个审查服务器实现packages/server/review.ts 与 apps/pi-extension/server/serverReview.ts中的落地形态。问题背景Overview 上下文为什么慢Plannotator 的 PR Overview 面板依赖 PR 上下文数据——包括 PR 描述body、状态state、草稿标记isDraft、标签labels、审查决策reviewDecision、可合并性与合并状态mergeable / mergeStateStatus、评论comments、审查reviews、审查线程reviewThreads、CI 检查checks和关联 IssuelinkedIssues。客户端通过唯一的 hook usePRContext.ts 请求这些数据并在 PR URL 变化时重置状态见 usePRContext.ts 中对prUrl变化的 reset 逻辑Overview 面板挂载时触发该请求见 ReviewPROverviewPanel.tsx。原方案的关键短板在于服务器直到收到/api/pr-context请求才开始执行耗时的 Provider 调用。也就是说客户端面板一打开就要等待一整轮fetchPRContext从零开始于是出现明显的加载闪烁loading flash。而客户端已经具备按 PR URL 重置、单一请求路径的形态因此最简且正确的改动是纯服务器端的——客户端无需任何变更。核心设计决策Decision Pressure预热必须达成两个看似矛盾的目标减少 Overview 加载闪烁同时不拖慢服务器就绪。决策文档给出了三个关键判断detached but owned脱离但拥有启动预热调用不能阻塞服务器启动但又必须能被端点复用。将 Promise 存入 Map 即构成足够的拥有权——端点可以await同一份在途工作而不是另起一个新的 Provider 调用。失败必须驱逐GitHub 场景下gh pr view失败会导致整个上下文抓取失败见 pr-github.ts 中fetchGhPRContext对非零退出码的抛错逻辑。如果失败后的 Promise 仍留在缓存里UI 上的重试按钮会反复拿到同一个失败结果。因此在 Promise 被拒绝时从缓存中删除该条目从而保留现有的重试语义。暂不抽公共抽象两个服务器的实现虽然相似但各自周边的状态是局部且运行时相关的。在各自文件内放一个微型 helper 能让改动范围最小避免引入一个没有更广复用面的新抽象。推荐实现会话级Mapstring, PromisePRContext决策文档给出的核心模式是一个以PR URL 为键、以in-flight 或已完成的fetchPRContextPromise 为值的会话级缓存。注意键的选择与既有prSwitchCache、prStackTreeCache保持一致SPIKE 文档指出主服务器的 PR 列表缓存为 30 秒、另有按 URL 的 switch 缓存与 stack tree 缓存参见 SPIKE-pr-context-warm-cache-20260630-110258.md。缓存与 helperconst prContextCache new Mapstring, PromisePRContext(); const getCachedPRContext (url: string, ref: PRRef): PromisePRContext { const cached prContextCache.get(url); if (cached) return cached; const promise fetchPRContext(ref).catch((error: unknown) { prContextCache.delete(url); throw error; }); prContextCache.set(url, promise); return promise; };这个 helper 完成五件事命中即返回既有 Promise未命中则创建fetchPRContext(ref)立即将 Promise 存入 Map避免并发请求重复发起 Provider 调用Promise 被拒绝时删除 Map 条目保住重试能力返回该 Promise。类型导入的运行时差异两个服务器对PRContext/PRRef的导入路径不同主服务器packages/server/review.ts可以直接从./pr导入Pi 服务器apps/pi-extension/server/serverReview.ts可从../generated/pr-types.js导入生成的类型若从包装模块导入PRRef有摩擦。三处调用点① 启动预热——不 awaitif (prRef prMetadata) { void getCachedPRContext(prMetadata.url, prRef).catch(() {}); }在服务器启动且初始 PR ref 可用时后台即开始抓取但不阻塞就绪。② PR 切换预热——不 awaitvoid getCachedPRContext(pr.metadata.url, prRef).catch(() {});当用户通过/api/pr-switch切换到新 PR、新的prRef确定之后立即对新 PR 的 URL 发起预热且不得延迟 switch 的响应。主服务器的 switch 路径在 review.ts 处更新prMetadata/prRef后立即预热Pi 服务器对应 serverReview.ts。③ 端点 await——复用同一份工作if (!isPRMode || !prRef || !prMetadata) { return Response.json({ error: Not in PR mode }, { status: 400 }); } const context await getCachedPRContext(prMetadata.url, prRef); return Response.json(context);/api/pr-context处理器await缓存的 Promise若预热尚未完成它等待的是同一个在途 Promise而不是再发一次 Provider 调用。Pi 实现中应使用 Pi 服务器的json(res, ...)helper。API 契约保持不变这是本次改动的一条硬约束——端点的对外行为完全不变spec-pr-context-warm-cache-20260630-110258.md 明确定义场景返回成功既有PRContextJSONProvider 失败{ error: string }状态码 500非 PR 模式{ error: Not in PR mode }状态码 400客户端 hook 依赖成功时的原始PRContextJSON 与失败时的{ error }结构usePRContext.ts因此契约稳定意味着客户端零改动。仓库现状从本地 Map 模式到共享的PRContextLiveCache值得说明的是当前仓库中的实际落地形态在决策文档所描绘的本地 Map 模式基础上进一步演进共享模块 packages/shared/pr-context-live.ts 中提供了createPRContextLiveCache内部以 URL 为键维护entriesMap见 pr-context-live.ts并实现了决策文档的核心语义warm(url, ref)发起 best-effort 后台刷新不等待pr-context-live.tsgetContext(url, ref)返回最新上下文并共享任何在途刷新pr-context-live.tsrefresh()合并 in-flight 请求、广播 loading/updated/error 事件并维护inflightPromisepr-context-live.ts。两个服务器均以同一方式接线createPRContextLiveCache({ fetchContext: fetchPRContext })创建实例再用一个warmPRContexthelper 包装warm主服务器 review.tsPi 服务器 serverReview.ts启动预热与切换预热分别落在 review.ts / review.ts 和 serverReview.ts / serverReview.ts/api/pr-context处理器则await prContextLive.getContext(prMetadata.url, prRef)review.ts、serverReview.ts。此外该共享缓存还支持watch()供/api/pr-context/stream实时推送与refreshAfterWrite()Provider 写入后立即刷新。这一实现有对应的单元测试佐证pr-context-live.test.ts 中的用例shares one in-flight refresh across warmup, GET, and watchers验证了预热、GET、watcher 三者共享同一个在途刷新Provider 只被调用一次——这正是决策文档中端点等待同一份工作语义的测试固化。fetchPRContext本身是运行时包装器主服务器在 pr.tsPi 服务器在 apps/pi-extension/server/pr.ts最终委托给共享的 Provider 实现。各 Provider 的失败特性也影响缓存语义GitHub 在gh pr view失败时整体抛错pr-github.ts而 GraphQL 抓取审查线程失败时降级为空列表GitLab 侧则从源码结构看采用并行只读调用组装上下文并将部分失败降级为空切片pr-gitlab.ts 起的fetchGlMRContext。验证方式按规格文档改动后用根脚本验证类型bun run typecheckbun test与bun run typecheck定义于 package.json 附近的根脚本。可选的聚焦手动检查清单启动一次 PR 审查立即打开 PR Overview确认/api/pr-context正常返回且命中预热缓存不再从零抓取切换到另一个 PR确认新 PR 的 Overview 仍能加载且当 Provider 抓取失败时重试仍然有效因为失败条目已被驱逐。风险与边界会话内可能过期若 PR 评论或 CI 检查在审查服务器打开期间发生变化会话级缓存的上下文可能变旧。这与请求的行为一致也符合既有的会话缓存风格PR 列表、switch、stack tree 缓存都是会话级的。慢调用下仍可能显示 loading对特别慢的 Provider 调用预热可能赶在 Overview 挂载之前仍未完成。此时 UI 仍会显示 loading但等待的是已在运行的那次抓取而不会额外启动第二次。一次多余的只读调用对于从未打开 Overview 上下文的 PR 审查服务器会多做一次 Provider 调用。由于 PR Overview 现在默认打开且该调用是只读的这个代价可以接受。明确不做的事What Not To Change不改客户端 hook 与 Overview 面板唯一请求路径与按 URL 重置逻辑保持不变不改/api/pr-context响应结构契约稳定是零客户端改动的前提不做跨服务器会话的持久化缓存生命周期限于当前会话不引入 TTL除非用户认为新鲜度比会话一致性更重要不在同一改动中重构 stack-tree 缓存保持改动范围聚焦于 PR 上下文预热。延伸阅读决策综述synthesis-pr-context-warm-cache-20260630-110258.md规格文档specs/pr-context-warm-cache-20260630-110258.md技术调研SPIKE-pr-context-warm-cache-20260630-110258.md共享缓存实现与测试packages/shared/pr-context-live.ts、packages/shared/pr-context-live.test.ts客户端消费端packages/review-editor/hooks/usePRContext.ts、packages/review-editor/dock/panels/ReviewPROverviewPanel.tsx赞分享【免费下载链接】plannotatorAnnotate and review coding agent plans and code diffs visually, share with your team, send feedback to agents with one click.项目地址https://gitcode.com/gh_mirrors/pl/plannotator点击查看免费下载相关推荐Husky.Net 常见问题解决方案Husky.Net 常见问题解决方案 项目基础介绍 Husky.Net 是一个用于简化 Git 钩子管理的开源项目主要面向 .NET 开发者。它允许开发者在提Nativefier构建缓存预热CI预加载缓存Nativefier构建缓存预热CI预加载缓存 在Nativefier的开发过程中构建速度和效率是开发者关注的重要问题。特别是在持续集成CI环境中频繁CLI桌面应用开发工具termux-packages构建缓存策略缓存预热与预加载termux packages构建缓存策略缓存预热与预加载 概述 Termux packages作为Android平台上最流行的Linux环境包管理系统其构开发工具包管理器构建工具上一篇OpenChamber 拖拽排序实践指南基于 dnd-kit 实现桌面与移动端一致的可排序交互下一篇免费开源风扇控制神器FanControl终极配置指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

自建CRM从选型到落地:数据可控、永久在线的销售团队实操指南
自建CRM从选型到落地:数据可控、永久在线的销售团队实操指南

销售团队的数据流转,始终是个绕不开的坎。我从最早用共享表格管客户,到后来折腾各种在线CRM,最后沉淀出一套可私有化部署、数据完全在自己手里的方案,就是这个DeskcommCRM。如果你也在纠结“为什么免费CRM总觉得不顺手”“客户数据… · 2026/9/25 12:25:52

2026楚慧杯CTF初赛Writeup:杂项、逆向与加密实战复盘
2026楚慧杯CTF初赛Writeup:杂项、逆向与加密实战复盘

2026第十届“楚慧杯”湖北省网络与数据安全实践能力竞赛初赛Writeup周六上午九点,把最后一台测试虚拟机快照做完,我们三个人的队伍准时打开了线上赛场入口。第十届楚慧杯初赛,八小时,一屏题目,从杂项到二进制&#xff… · 2026/9/25 12:25:46

Neo4j社区版5.24.2离线部署实战:从tar包解压到远程访问与数据导入
Neo4j社区版5.24.2离线部署实战:从tar包解压到远程访问与数据导入

简介:Neo4j社区版5.24.2的Unix平台tar.gz安装包,面向需要构建图数据模型、处理复杂关系网络的开发者与教学研究人员。相比关系型数据库,它以节点和关系组织数据,配合原生Cypher查询语言,在社交网络、推荐系统、欺诈检测… · 2026/9/25 12:25:46

PLSQL Developer连接Oracle报OCI.dll错误的完整解决方案
PLSQL Developer连接Oracle报OCI.dll错误的完整解决方案

简介:本资源是面向Oracle数据库初学者与开发人员的PL/SQL Developer连接实战配置包,聚焦解决轻量级客户端环境下高效连接远程Oracle数据库的核心问题。压缩包内含45个文件,涵盖20个关键DLL动态库(如oci.dll、oraociei11.dll&#… · 2026/9/25 13:06:08

LeanCTX配置与故障排查终极指南:每一把调优杠杆与doctor诊断清单
LeanCTX配置与故障排查终极指南:每一把调优杠杆与doctor诊断清单

LeanCTX配置与故障排查终极指南:每一把调优杠杆与doctor诊断清单 【免费下载链接】lean-ctx LeanCTX — Context Intelligence for AI systems. 项目地址: https://gitcode.com/gh_mirrors/le/lean-ctx LeanCTX(Lean Context)是一款本… · 2026/9/25 13:06:02

MicYou主题定制指南:Material 3动态取色、袖珍模式与多语言一键切换
MicYou主题定制指南:Material 3动态取色、袖珍模式与多语言一键切换

MicYou主题定制指南:Material 3动态取色、袖珍模式与多语言一键切换 【免费下载链接】MicYou MicYou is a powerful tool that turns your Android device into a high-quality microphone for your PC. 项目地址: https://gitcode.com/gh_mirrors/mi/MicYou … · 2026/9/25 13:06:02

n8n:开源自动化工作流平台自托管部署与实战
n8n:开源自动化工作流平台自托管部署与实战

这一期“一天一个强大的网站”不打算推荐一个你打开收藏就再也不用的效率工具,而是推荐一个真正值得跑在你自己服务器上的开源项目:n8n。如果你平常写代码,一定遇到过这类场景:外部系统回调了一个业务事件,需要清洗、转… · 2026/9/25 13:05:56

DeepSeekHarness(番外01):MCP与Skill配置不再手改YAML,一条命令接入15个服务器
DeepSeekHarness(番外01):MCP与Skill配置不再手改YAML,一条命令接入15个服务器

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 13:05:49

Windows 10麦克风权限失效的三层根因与修复指南
Windows 10麦克风权限失效的三层根因与修复指南

1. 这不是权限开关失灵,而是Windows 10隐私架构的“默认拒绝”逻辑在生效 你点开“设置→隐私→麦克风”,明明把“允许应用访问你的麦克风”滑块拉到了最右边,可Zoom、腾讯会议、甚至系统自带的语音识别依然提示“麦克风被禁用”&#xff1b… · 2026/9/25 13:05:43

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码