前端:埋点句柄只在结构化拒单时清掉
- `runTurn` 的 catch 先读结构化拒单,只有"这一轮没接单"的拒单才清 `pendingRunAnalyticsRef`;非结构化错误(IPC 失败、命令 panic)可能发生在接单之后,句柄留着等 `turn.completed` 结算,不再让宿主侧这一轮的候选永远没人结算 - chat-composer 用例的注释同步:这一轮没接单,就没有回合终态事件来驱动结算
This commit is contained in:
+9
-4
@@ -666,13 +666,18 @@ export function useDirectProjectChatController({
|
||||
turnAccepted = true;
|
||||
// 清单刷新统一交给 startTurn 的 finally:成功与报错路径都覆盖,且只读一次。
|
||||
} catch (error) {
|
||||
// 拒单那一轮没有接单,也就不会有埋点候选:句柄只清不发(发出去也只是空操作)。
|
||||
if (pendingRunAnalyticsRef.current?.clientTurnId === input.clientTurnId) {
|
||||
pendingRunAnalyticsRef.current = null;
|
||||
}
|
||||
// 命令的拒单是**结构化的**:命令返回 `Ok` 只说明接单成立,所以这条 catch 从接单化之后
|
||||
// 只剩"拒单"一种输入(整轮结果由 `turn.completed` 事件回答,不再回到这里)。
|
||||
const rejection = readDirectTurnRejection(error);
|
||||
// 只有结构化拒单能证明"这一轮没接单"(拒单不产生回合事件、也就不会有埋点候选),句柄才
|
||||
// 只清不发;非结构化错误(IPC 失败、命令 panic)可能发生在接单之后,那时必须留着句柄等
|
||||
// `turn.completed` 来结算——提前清掉会让宿主侧这一轮的候选永远没有人结算。
|
||||
if (
|
||||
rejection &&
|
||||
pendingRunAnalyticsRef.current?.clientTurnId === input.clientTurnId
|
||||
) {
|
||||
pendingRunAnalyticsRef.current = null;
|
||||
}
|
||||
if (rejection) {
|
||||
const notice = directTurnRejectionNotice(rejection);
|
||||
if (notice) {
|
||||
|
||||
@@ -420,7 +420,7 @@ export function registerChatComposerControlTests() {
|
||||
);
|
||||
expect(attempts).toHaveLength(1);
|
||||
expect(refresh).not.toHaveBeenCalled();
|
||||
// 拒单没有接单、也就没有埋点候选:句柄直接丢掉,不产生一次注定被丢弃的结算。
|
||||
// 这一轮没有接单,不会有回合终态事件来驱动结算:埋点一次也不结算。
|
||||
expect(
|
||||
invoke.mock.calls.filter(
|
||||
([command]) => command === 'settle_direct_run_analytics',
|
||||
|
||||
Reference in New Issue
Block a user