feat(student-bff): 完整实现 student-bff 聚合层
包含 src 全部实现、Dockerfile、shared-ts/bff 包等
This commit is contained in:
125
services/student-bff/src/shared/action-state.ts
Normal file
125
services/student-bff/src/shared/action-state.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* 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 Degradable>(
|
||||
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;
|
||||
Reference in New Issue
Block a user