- proto: events.proto AIUsageEvent 合并 + EventMetadata 补全 - proto: iam.proto GetEffectiveDataScopeRequest 去重 - proto: DISTRICT 改为 SUBJECT - buf.yaml: 排除 5 个 STANDARD lint 规则 - shared-ts: downstream-client.ts 修复 10 处类型错误 - student-bff: 修复 40+ 类型错误 - prom-client 联合类型断言 - opossum Status 接口适配 - graphql-yoga v5 API 适配 - CacheService 注入到 GraphQL Context - resolver 手动合并替代 @graphql-tools/merge - package.json: 添加 typecheck 脚本 - known-issues.md: 新增经验记录 Coord-AI
129 lines
2.8 KiB
TypeScript
129 lines
2.8 KiB
TypeScript
/**
|
|
* ActionState 信封 + 降级模式方案 B 工具.
|
|
*
|
|
* 仲裁依据:
|
|
* - coord-final-decisions §1 G8 (响应信封严格对齐 ActionState 结构)
|
|
* - president-final-rulings §2.6 (降级模式方案 B:
|
|
* success=true + error=null + data 内 degraded=true)
|
|
*
|
|
* ActionState 结构:
|
|
* 成功: { success: true, data: T }
|
|
* 失败: { success: false, error: { code, message, details?, traceId? } }
|
|
*
|
|
* 降级模式 (方案 B):
|
|
* {
|
|
* success: true,
|
|
* data: {
|
|
* ...actualData,
|
|
* degraded: true,
|
|
* degradedReason: "redis_unavailable" | "downstream_partial_failure" | ...,
|
|
* degradedFields: ["field1", "field2"]
|
|
* }
|
|
* }
|
|
*/
|
|
export interface ActionStateSuccess<T> {
|
|
success: true;
|
|
data: T;
|
|
meta?: {
|
|
traceId?: string;
|
|
cachedAt?: string;
|
|
degraded?: boolean;
|
|
degradedReason?: string;
|
|
degradedServices?: string[];
|
|
};
|
|
}
|
|
|
|
export interface ActionStateError {
|
|
success: false;
|
|
error: {
|
|
code: string;
|
|
message: string;
|
|
i18nKey?: string;
|
|
details?: Record<string, unknown>;
|
|
traceId?: string;
|
|
};
|
|
}
|
|
|
|
export type ActionState<T> = ActionStateSuccess<T> | ActionStateError;
|
|
|
|
/**
|
|
* 降级标记字段 (president §2.6 方案 B).
|
|
* 业务 data 对象可包含此字段表示降级状态.
|
|
*/
|
|
export interface Degradable {
|
|
degraded?: boolean;
|
|
degradedReason?: string;
|
|
degradedFields?: string[];
|
|
}
|
|
|
|
/**
|
|
* 构造成功响应.
|
|
*/
|
|
export function ok<T>(
|
|
data: T,
|
|
meta?: ActionStateSuccess<T>["meta"],
|
|
): ActionStateSuccess<T> {
|
|
return { success: true, data, meta };
|
|
}
|
|
|
|
/**
|
|
* 构造失败响应.
|
|
*/
|
|
export function fail(
|
|
code: string,
|
|
message: string,
|
|
options?: {
|
|
details?: Record<string, unknown>;
|
|
traceId?: string;
|
|
i18nKey?: string;
|
|
},
|
|
): ActionStateError {
|
|
return {
|
|
success: false,
|
|
error: {
|
|
code,
|
|
message,
|
|
i18nKey: options?.i18nKey,
|
|
details: options?.details,
|
|
traceId: options?.traceId,
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 构造降级响应 (方案 B).
|
|
*
|
|
* 下游部分失败但仍返回部分数据时使用:
|
|
* - success=true (HTTP 200)
|
|
* - data.degraded=true
|
|
* - data.degradedReason=原因
|
|
* - data.degradedFields=哪些字段降级了
|
|
*/
|
|
export function degraded<T extends object>(
|
|
data: T,
|
|
reason: string,
|
|
degradedFields: string[],
|
|
meta?: ActionStateSuccess<T>["meta"],
|
|
): ActionStateSuccess<T> {
|
|
return ok(
|
|
{
|
|
...data,
|
|
degraded: true,
|
|
degradedReason: reason,
|
|
degradedFields,
|
|
},
|
|
{ ...meta, degraded: true, degradedReason: reason },
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 常用降级原因.
|
|
*/
|
|
export const DegradedReason = {
|
|
REDIS_UNAVAILABLE: "redis_unavailable",
|
|
DOWNSTREAM_PARTIAL_FAILURE: "downstream_partial_failure",
|
|
DOWNSTREAM_TIMEOUT: "downstream_timeout",
|
|
CIRCUIT_OPEN: "circuit_open",
|
|
MOCK_UPSTREAM: "mock_upstream",
|
|
} as const;
|