fix(chat): lower unavailable media logs

This commit is contained in:
2026-07-14 17:19:10 +08:00
parent 3c48aa7909
commit 49788a04d5
4 changed files with 153 additions and 21 deletions
+26 -1
View File
@@ -1,9 +1,13 @@
import { describe, expect, it } from "vitest";
import { afterEach, describe, expect, it, vi } from "vitest";
import { AppException, ExceptionCode } from "@/core/errors";
import { Result, toError } from "../result";
afterEach(() => {
vi.restoreAllMocks();
});
describe("Result error normalization", () => {
it("normalizes unknown thrown values to AppException", async () => {
const result = await Result.wrap(async () => {
@@ -25,4 +29,25 @@ describe("Result error normalization", () => {
expect(error.message).toBe("Network connection failed.");
expect((error as AppException).code).toBe(ExceptionCode.network);
});
it("allows expected failures to be logged at info level", async () => {
const info = vi.spyOn(console, "info").mockImplementation(() => undefined);
const error = vi
.spyOn(console, "error")
.mockImplementation(() => undefined);
const result = await Result.wrap(
async () => {
throw new Error("expected failure");
},
{ errorLogLevel: "info" },
);
expect(Result.isErr(result)).toBe(true);
expect(info).toHaveBeenCalledWith(
expect.stringContaining("INFO [Result] Result.wrap caught exception"),
expect.any(Object),
);
expect(error).not.toHaveBeenCalled();
});
});
+22 -5
View File
@@ -17,6 +17,14 @@ export type Result<T> =
/** Result.wrap 专用 logger —— 自动带 component: "Result" 标签 */
const log = new Logger("Result");
type ResultErrorLogLevel = "info" | "error";
export interface ResultWrapOptions {
errorLogLevel?:
| ResultErrorLogLevel
| ((error: Error) => ResultErrorLogLevel);
}
export const Result = {
/** 构造成功结果。 */
ok<T>(data: T): Result<T> {
@@ -56,15 +64,24 @@ export const Result = {
* 3. 不重新抛出 —— 调用方拿到的永远是 `Result<T>`throw 风格调用方可在
* 最外层显式 `throw r.error`
*/
async wrap<T>(thunk: () => Promise<T>): Promise<Result<T>> {
async wrap<T>(
thunk: () => Promise<T>,
options?: ResultWrapOptions,
): Promise<Result<T>> {
try {
return Result.ok(await thunk());
} catch (e) {
const err = toError(e);
log.error(
{ err, stack: err.stack, type: err.constructor.name },
"Result.wrap caught exception",
);
const logLevel =
typeof options?.errorLogLevel === "function"
? options.errorLogLevel(err)
: options?.errorLogLevel ?? "error";
const details = { err, stack: err.stack, type: err.constructor.name };
if (logLevel === "info") {
log.info(details, "Result.wrap caught exception");
} else {
log.error(details, "Result.wrap caught exception");
}
return Result.err(err);
}
},