fix(chat): isolate cached data by identity

Scope message and media caches to the active user or guest identity. Preserve identity snapshots across async chat flows and discard legacy unscoped message data during the IndexedDB upgrade.
This commit is contained in:
2026-07-13 16:54:34 +08:00
parent 7c69b6cd8a
commit b126b83c4c
14 changed files with 601 additions and 133 deletions
@@ -68,22 +68,29 @@ export interface IChatRepository {
markPrivateMessageUnlockedInLocal(
messageId: string,
patch?: UnlockedPrivateMessageLocalPatch,
cacheIdentity?: string,
): Promise<Result<void>>;
/** 把一条消息写入本地存储。 */
saveMessageToLocal(message: ChatMessage): Promise<Result<void>>;
saveMessageToLocal(
message: ChatMessage,
cacheIdentity?: string,
): Promise<Result<void>>;
/** 批量覆盖写入:先清空本地存储,再写入新列表。 */
saveMessagesToLocal(messages: readonly ChatMessage[]): Promise<Result<void>>;
saveMessagesToLocal(
messages: readonly ChatMessage[],
cacheIdentity?: string,
): Promise<Result<void>>;
/** 读取所有本地消息,按 dbId 升序。 */
getLocalMessages(): Promise<Result<ChatMessage[]>>;
getLocalMessages(cacheIdentity?: string): Promise<Result<ChatMessage[]>>;
/** 清空本地消息。 */
clearLocalMessages(): Promise<Result<void>>;
clearLocalMessages(cacheIdentity?: string): Promise<Result<void>>;
/** 获取本地消息数量。 */
getLocalMessageCount(): Promise<Result<number>>;
getLocalMessageCount(cacheIdentity?: string): Promise<Result<number>>;
/** 获取本地缓存的图片 / 音频。 */
getCachedMedia(
@@ -93,15 +100,18 @@ export interface IChatRepository {
/** 下载并缓存远程图片 / 音频。 */
cacheRemoteMedia(
input: CacheRemoteChatMediaInput,
cacheIdentity?: string,
): Promise<Result<LocalChatMediaRow>>;
/** 后台预缓存历史消息中的图片 / 音频。失败不影响聊天主流程。 */
prefetchMediaForMessages(
messages: readonly ChatMessage[],
cacheIdentity?: string,
): Promise<Result<void>>;
/** 后台预缓存发送响应中的图片 / 音频。失败不影响聊天主流程。 */
prefetchMediaForSendResponse(
response: ChatSendResponse,
cacheIdentity?: string,
): Promise<Result<void>>;
}