feat(appdata): 冻结兼容写入入口

This commit is contained in:
2026-07-08 16:36:16 +08:00
parent 18380edda8
commit 36202028d2
8 changed files with 294 additions and 5 deletions

View File

@@ -29,6 +29,14 @@ type ServerDataConflictBody<T> = {
currentVersion: string | null;
};
type ServerDataWriteFrozenBody = {
code: 'APP_DATA_WRITE_FROZEN';
key: ServerDataKey;
state: 'write_frozen' | 'read_only_archive';
replacement: string;
note?: string;
};
const serverDataVersions = new Map<ServerDataKey, string | null>();
const serverDataCache = new Map<ServerDataKey, {
value: unknown | null;
@@ -61,8 +69,21 @@ export class ServerDataConflictError<T = unknown> extends Error {
}
}
export class ServerDataWriteFrozenError extends Error {
constructor(
public readonly key: ServerDataKey,
public readonly state: 'write_frozen' | 'read_only_archive',
public readonly replacement: string,
public readonly note?: string,
) {
super(`AppData 写入已冻结,请改用 ${replacement}`);
this.name = 'ServerDataWriteFrozenError';
}
}
function getServerDataSaveErrorMessage(error: unknown) {
if (error instanceof ServerDataConflictError) return '数据已被其他用户更新,请刷新后重试';
if (error instanceof ServerDataWriteFrozenError) return error.message;
if (error instanceof Error && error.message) return error.message;
return '保存失败,请检查网络或 API 服务';
}
@@ -153,6 +174,20 @@ async function putServerData<T>(key: ServerDataKey, value: T): Promise<void> {
notifyServerDataSaveFailure(key, conflict);
throw conflict;
}
if (
error instanceof ApiRequestError &&
error.status === 409 &&
isServerDataWriteFrozenBody(error.body, key)
) {
const frozen = new ServerDataWriteFrozenError(
error.body.key,
error.body.state,
error.body.replacement,
error.body.note,
);
notifyServerDataSaveFailure(key, frozen);
throw frozen;
}
notifyServerDataSaveFailure(key, error);
throw error;
}
@@ -173,3 +208,18 @@ function isServerDataConflictBody<T>(
: true)
);
}
function isServerDataWriteFrozenBody(
body: unknown,
key: ServerDataKey,
): body is ServerDataWriteFrozenBody {
return (
typeof body === 'object' &&
body !== null &&
(body as { code?: unknown }).code === 'APP_DATA_WRITE_FROZEN' &&
(body as { key?: unknown }).key === key &&
((body as { state?: unknown }).state === 'write_frozen' ||
(body as { state?: unknown }).state === 'read_only_archive') &&
typeof (body as { replacement?: unknown }).replacement === 'string'
);
}