Back to Prompt Optimizer

115-IPC序列化修复与数据一致性

docs/archives/115-ipc-serialization-fixes/README.md

2.10.28.8 KB
Original Source

115-IPC序列化修复与数据一致性

📋 概述

解决Electron应用中Vue响应式对象IPC序列化问题,以及由此引发的数据一致性问题。

📝 专注领域:本文档专注于Vue响应式对象的IPC序列化问题,其他IPC架构问题请参考112-desktop-ipc-fixes

🚨 核心问题

1. IPC序列化错误

An object could not be cloned

原因:Vue响应式对象包含不可序列化的属性(Proxy、Symbol等),无法通过Electron IPC传递。

2. 数据一致性问题

修改gemini模型apiKey → 其他模型(openai, deepseek等)全部消失

根本原因:ModelManager的updateData回调函数基于不完整的存储数据进行操作。

✅ 解决方案

1. IPC层序列化保护

safeSerialize函数

typescript
/**
 * 安全序列化函数,用于清理Vue响应式对象
 * 确保所有通过IPC传递的对象都是纯净的JavaScript对象
 */
function safeSerialize(obj) {
  if (obj === null || obj === undefined) {
    return obj;
  }
  
  // 对于基本类型,直接返回
  if (typeof obj !== 'object') {
    return obj;
  }
  
  try {
    return JSON.parse(JSON.stringify(obj));
  } catch (error) {
    console.error('[IPC Serialization] Failed to serialize object:', error);
    throw new Error(`Failed to serialize object for IPC: ${error.message}`);
  }
}

IPC处理器应用

typescript
// 模型管理相关
ipcMain.handle('model-updateModel', async (event, id, updates) => {
  try {
    const safeUpdates = safeSerialize(updates);
    await modelManager.updateModel(id, safeUpdates);
    return createSuccessResponse(null);
  } catch (error) {
    return createErrorResponse(error);
  }
});

ipcMain.handle('model-addModel', async (event, model) => {
  try {
    const safeModel = safeSerialize(model);
    const { key, ...config } = safeModel;
    await modelManager.addModel(key, config);
    return createSuccessResponse(null);
  } catch (error) {
    return createErrorResponse(error);
  }
});

// 模板管理相关
ipcMain.handle('template-createTemplate', async (event, template) => {
  try {
    const safeTemplate = safeSerialize(template);
    await templateManager.saveTemplate(safeTemplate);
    return createSuccessResponse(null);
  } catch (error) {
    return createErrorResponse(error);
  }
});

ipcMain.handle('template-updateTemplate', async (event, id, updates) => {
  try {
    const existingTemplate = await templateManager.getTemplate(id);
    const safeUpdates = safeSerialize(updates);
    const updatedTemplate = { ...existingTemplate, ...safeUpdates, id };
    await templateManager.saveTemplate(updatedTemplate);
    return createSuccessResponse(null);
  } catch (error) {
    return createErrorResponse(error);
  }
});

// 历史记录相关
ipcMain.handle('history-addRecord', async (event, record) => {
  try {
    const safeRecord = safeSerialize(record);
    const result = await historyManager.addRecord(safeRecord);
    return createSuccessResponse(result);
  } catch (error) {
    return createErrorResponse(error);
  }
});

ipcMain.handle('history-createNewChain', async (event, record) => {
  try {
    const safeRecord = safeSerialize(record);
    const result = await historyManager.createNewChain(safeRecord);
    return createSuccessResponse(result);
  } catch (error) {
    return createErrorResponse(error);
  }
});

ipcMain.handle('history-addIteration', async (event, params) => {
  try {
    const safeParams = safeSerialize(params);
    const result = await historyManager.addIteration(safeParams);
    return createSuccessResponse(result);
  } catch (error) {
    return createErrorResponse(error);
  }
});

2. 业务逻辑层数据一致性修复

问题根因

ModelManager的updateData回调函数错误地基于可能不完整的存储数据:

typescript
// ❌ 错误的实现
(currentModels) => {
  const models = currentModels || {}; // 可能不完整!
  return {
    ...models, // 基于不完整的数据
    [key]: updatedConfig
  };
}

正确的解决方案

typescript
// ✅ 正确的实现
(currentModels) => {
  // 使用内存中的完整模型列表作为基础
  const models = { ...this.models };
  
  // 如果存储中有数据,合并到内存状态中
  if (currentModels) {
    Object.assign(models, currentModels);
  }
  
  return {
    ...models, // 完整的模型列表
    [key]: updatedConfig
  };
}

修复范围

所有ModelManager的数据更新方法:

  1. addModel - 添加模型时保持完整列表
  2. updateModel - 更新模型时保持完整列表
  3. deleteModel - 删除模型时基于完整列表
  4. enableModel - 启用模型时保持完整列表
  5. disableModel - 禁用模型时保持完整列表

3. 双重保护机制

Vue组件 → safeSerialize → IPC → 业务逻辑修复 → 增强的FileStorageProvider
         ↑                    ↑                    ↑
    清理响应式对象        数据完整性保障        原子性操作+备份保护

🛡️ 核心原则

1. 分层修复原则

在正确的层级解决对应的问题

  • IPC传输问题 → IPC层 (main.js)
  • 业务逻辑错误 → 业务逻辑层 (ModelManager)
  • 存储安全问题 → 存储层 (FileStorageProvider)

2. 数据完整性优先原则

始终基于完整的数据进行操作

typescript
// 错误:基于可能不完整的存储状态
const models = currentModels || {};

// 正确:基于内存中的完整状态
const models = { ...this.models };
if (currentModels) {
  Object.assign(models, currentModels);
}

3. 边界清理原则

在IPC边界清理Vue响应式对象

typescript
// 在IPC处理器中统一清理
const safeData = safeSerialize(reactiveData);

🧪 测试验证

1. IPC序列化测试

typescript
describe('IPC Serialization', () => {
  it('should handle Vue reactive objects', async () => {
    const reactiveObj = reactive({ key: 'value', nested: { prop: 'test' } });
    const serialized = safeSerialize(reactiveObj);
    
    expect(serialized).toEqual({ key: 'value', nested: { prop: 'test' } });
    expect(typeof serialized).toBe('object');
    expect(serialized.constructor).toBe(Object);
  });
});

2. 数据一致性测试

typescript
describe('Data Consistency', () => {
  it('should maintain complete model list when updating single model', async () => {
    // 初始化完整的模型列表
    const initialModels = { openai: config1, gemini: config2, deepseek: config3 };
    
    // 更新单个模型
    await modelManager.updateModel('gemini', { apiKey: 'new-key' });
    
    // 验证其他模型没有丢失
    const allModels = await modelManager.getAllModels();
    expect(Object.keys(allModels)).toHaveLength(3);
    expect(allModels.openai).toBeDefined();
    expect(allModels.deepseek).toBeDefined();
  });
});

📊 技术价值

1. 问题解决

  • ✅ 彻底解决IPC序列化错误
  • ✅ 修复数据丢失问题
  • ✅ 建立数据一致性保障机制

2. 架构完善

  • ✅ 分层修复,职责清晰
  • ✅ 双重保护机制
  • ✅ 统一的错误处理

3. 开发体验

  • ✅ 透明的序列化处理
  • ✅ 可靠的数据操作
  • ✅ 完善的测试覆盖

🔗 相关文档

💡 最佳实践

IPC序列化

  • ✅ 在ElectronProxy层统一处理序列化(已完成)
  • ✅ 使用通用的safeSerializeForIPC函数(已完成)
  • ✅ 保持调用方的透明性(已完成)
  • ✅ 清理UI层的手动序列化代码(已完成)

数据一致性

  • 基于完整的内存状态进行更新
  • 合并存储中的增量更新
  • 确保返回完整的数据集

错误处理

  • 在正确的层级处理对应的错误
  • 提供详细的错误信息
  • 建立完整的错误恢复机制

架构演进

这些修复经历了两个阶段:

  1. 第一阶段:在UI层手动序列化(112-desktop-ipc-fixes)
  2. 第二阶段:移到ElectronProxy层自动序列化(当前方案)

最终实现了对Vue组件完全透明的IPC序列化处理,确保了Electron应用中数据操作的可靠性和一致性。

📁 文档结构

本目录包含以下文档:

  • README.md - 主要概述和最佳实践
  • proxy-layer-serialization.md - ElectronProxy层序列化技术实现
  • architecture-evolution.md - 架构演进完整记录

🔗 相关文档

💡 文档分工

112专注于:IPC架构完整性、异步接口设计、语言切换等功能性问题 115专注于:Vue响应式对象序列化、ElectronProxy层自动化处理