Files
JRedisDesktop/docs/PROJECT_REVIEW.md
Jokul ad21900a6f feat(N4): virtual scrolling for Set/Zset/List editors
- Create VirtualScrollList.vue component using @tanstack/vue-virtual
  - Props: items, itemHeight, overscan, height
  - Events: scrollEnd (for infinite loading)
  - Slots: default (item rendering), empty
- SetEditor: replace v-for with VirtualScrollList, handles 100k+ members
- ZsetEditor: replace v-for with VirtualScrollList, preserves filter/sort
- ListEditor: replace pagination with virtual scroll + infinite loading
  - Initial load 100 items, auto-loads 100 more on scrollEnd
  - Shows loaded/total count + loading indicator
- HashEditor: kept as-is (HSCAN limits to 100 items, el-table handles fine)
- docs: mark N4 complete, update problem E priority to medium
2026-07-12 15:04:08 +08:00

10 KiB
Raw Permalink Blame History

JRedisDesktop 项目架构分析与需求规划

审查日期:2026-07-12 缺陷修复:54 个问题已全部处理(P0×6 + P1×11 + P2×14 + P3×9) 本文档聚焦:系统性架构问题深度分析 + 可开发需求规划


一、系统性架构问题分析

经过全量缺陷修复后,以下 5 个架构级问题中部分已通过点修复解决,但系统性方案仍需推进。

问题 A:资源生命周期管理

已解决的点:

  • app.on('will-quit') 调用 disconnectAll() + stopAllPubSubClients() -- 退出时连接/订阅/监控不再泄漏
  • KeyDetail TTL 定时器移入 onMounted,onUnmounted 清理
  • CliView IPC 监听器(publishMessage/monitorMessage)返回清理函数,卸载时调用
  • PubSub/Monitor 添加 sender.isDestroyed() 检查 + destroyed 事件自动清理

仍存在的系统性问题:

  • 各组件/store 仍各自管理 setInterval/addEventListener/IPC 监听,无统一注册机制
  • stores/connection.tshealthTimers Map 无 dispose 路径(HMR 时泄漏)
  • stores/app.tstheme.onOsUpdated 回调永不移除
  • StatusView.vuerefreshTimerSlowLogView.vue 的定时器仍各自管理

架构级方案:

引入 useDisposable composable:
  const { register, dispose } = useDisposable()
  register(setInterval(...))  // 自动在 onScopeDispose 时清理
  register(ipcListener)       // 自动移除

或使用 VueUse 的 tryOnScopeDispose:
  tryOnScopeDispose(() => clearInterval(timer))

优先级: -- 当前点修复已解决崩溃级问题,剩余的是 HMR 场景下的泄漏,生产环境影响小。


问题 B:安全模型

已解决的点:

  • 凭据加密:storage:saveConnection 加密 auth/sshPassword/sshPassphrase,getConnections 解密
  • safeStorage 不可用时抛出错误而非明文回退
  • customFormat 白名单(xxd/jq/python3/python/php/column)
  • redis:execute 拦截 FLUSHALL/FLUSHDB/SHUTDOWN/DEBUG,新增 executeUnsafe 供 CLI
  • 移除 dangerouslyUseHTMLString,改用纯文本

仍存在的系统性问题:

  • executeUnsafe 在渲染进程中可被任意调用,妥协的渲染进程仍能执行危险命令
  • 凭据解密在 getConnections 中批量进行,解密后的明文密码在渲染进程内存中停留
  • SSH 私钥路径和 TLS 证书路径未校验(路径遍历)

架构级方案:

  • executeUnsafe 加来源校验:仅允许从 CliView 的 IPC 事件调用(检查 event.senderFrame 来源)
  • 渲染进程不持有明文密码:连接时传递密码到主进程,主进程自行解密使用,渲染进程只存加密串
  • 路径校验:expandHomePath 后检查路径不在敏感目录外

优先级: -- contextIsolation: true + nodeIntegration: false 已提供基础隔离,当前安全水平可接受。


问题 C:错误处理策略

已解决的点:

  • withLog 提取实际连接 ID
  • win-state.ts 写错误 console.error
  • TLS/SSH 文件读取失败 console.warn
  • Monitor .catch() 处理 rejection
  • updater.ts 防重复注册

仍存在的系统性问题:

  • redis:connect 捕获错误返回 { success: false, error } 对象,其他 handler 直接 throw -- 两种模式混用
  • redis:disconnect 无 try/catch,内部错误成为未处理 rejection
  • PubSub sub.subscribe()/sub.psubscribe() 返回的 Promise 未 await
  • 渲染进程各处 IPC 调用的错误处理不统一(有的 try/catch + ElMessage,有的无处理)

架构级方案:

// 主进程:统一 IPC wrapper
function safeHandle(channel: string, handler: (...args) => Promise<any>) {
  ipcMain.handle(channel, async (e, ...args) => {
    try { return await handler(e, ...args) }
    catch (err) { throw new Error(serializeError(err)) }
  })
}

// 渲染进程:统一调用封装
async function safeInvoke<T>(fn: () => Promise<T>, errorMsg?: string): Promise<T | undefined> {
  try { return await fn() }
  catch (err) { ElMessage.error(errorMsg || err.message); return undefined }
}

优先级: -- 不影响功能,但调试困难,用户体验不一致。


问题 D:类型安全

已解决的点:

  • preload/index.d.ts 15+ 处 any 替换为具体类型(connect/scanKeys/hashScan/dialog.openFile/stream 等)
  • 内联定义 ConnectionConfig/AppSettings/CommandEntry 接口
  • ConnectionConfig 添加 version 字段 + migrateConnections() 迁移函数
  • WRITE_COMMANDS 补全 30+ 写命令

仍存在的系统性问题:

  • connection.tssshConfig: anytlsOpts: anyclusterOptions: anyredis as any 仍未消除
  • stream.ts 多处 as any 绕过 ioredis 类型
  • ipc-handlers.tswithLog 参数仍为 any[]
  • 渲染进程组件中多处 (item: any) 类型断言

架构级方案:

  • 从 ioredis 导入 Cluster 类型替换 redis as any
  • 定义 SSHClientConfigTLSOptions 接口替换 any
  • stream.ts 使用 ioredis 的 xgroup/xinfo 方法签名
  • 渲染进程定义 Redis 命令结果的类型接口

优先级: -- 类型不准确不影响运行,但影响可维护性和 IDE 体验。


问题 E:性能策略

已解决的点:

  • KeyList 批量导出改为 Promise.allSettled 分批并行(每批 20)
  • key.tsuseConnectionStore() 获取 separator,消除每次 SCAN 的 IPC 往返
  • HashEditor HTTL 改为点击字段时按需加载
  • SCAN 空模式规范化为 '*'

仍存在的系统性问题:

  • KeyList 树视图大数据量时渲染卡顿
  • 无 SCAN 结果缓存,频繁切换 DB 重复扫描
  • scanKeys 全量加载到前端,无分页/懒加载

架构级方案:

  • KeyList 树视图使用 el-tree-v2(虚拟滚动树)
  • SCAN 结果分页:前端维护 cursor,滚动到底部加载下一页
  • 连接级别的 SCAN 结果缓存(LRU)

优先级: -- 编辑器虚拟滚动已解决,剩余 KeyList 树视图和 SCAN 分页问题。


二、可开发需求清单

已完成需求

# 需求 完成方式
N1 凭据加密加固 P0#1 修复:storage:saveConnection 加密敏感字段
N2 资源生命周期管理器 P0#4 + P1#8/9/10 修复:退出清理 + 定时器/监听器清理
N6 命令白名单中间件 P0#3 修复:BLOCKED_COMMANDS + executeUnsafe
N15 TTL 实时倒计时优化 P1#8 修复:定时器移入 onMounted
N16 主题完整适配 P2#19 修复:ReJsonEditor :theme="monacoTheme"
N17 i18n 补全 P3#37 修复:KeyDetail/TitleBar/Sidebar 硬编码替换
N25 TypeScript 严格化(部分) P3#36/42 修复:preload d.ts 15+ 处 any 消除
N4 虚拟滚动 创建 VirtualScrollList.vue(@tanstack/vue-virtual);Set/Zset/List 编辑器改造完成

高优先级需求

# 需求 用户价值 复杂度 实现思路
N5 Stream Consumer Group 完整化 ACK 已实现但未用,消费组可视化不全 StreamEditor 接入 redis:streamAck;加 pending entries 列表、XPEL CLAIM 功能
N3 CLI 事务体验优化 当前 MULTI/EXEC 功能正确但 UX 不佳(未显示 QUEUED 状态) 事务模式下检查返回值是否为 "QUEUED",非 QUEUED 时警告用户

中优先级需求

# 需求 用户价值 复杂度 实现思路
N7 Cluster/Sentinel 完善 生产环境主流部署,当前 cluster 分支已有但拓扑不可视 节点拓扑可视化(CLUSTER NODES)、failover 操作、slot 分布图
N8 ACL 用户管理 Redis 6+ ACL 已普及,当前只能用 CLI 新建 ACL 视图:用户 CRUD、权限矩阵、ACL WHOAMI/ACL LIST
N9 数据导入导出 迁移/备份场景,KeyList 已有导出雏形 导出:RDB/DUMP/JSON 格式;导入:批量 SET/pipeline
N10 Function 管理(Redis 7+) 替代 EVAL 的服务端函数 新建 Function 视图:FUNCTION LIST/LOAD/DELETE/调用
N11 大 Key 扫描 生产排障刚需,MEMORY USAGE 扫描已有 扩展为后台任务 + 排序 + 导出报告 + 可视化分布
N12 Latency Monitor 补充慢日志的延迟诊断 LATENCY HISTORY/LATENCY DOCTOR 视图
N13 PubSub 可视化 当前仅 CLI 内嵌,无独立视图 新建 PubSub 视图:频道树、消息流、JSON 高亮、订阅状态
N14 连接分组/标签 连接多了难管理 ConnectionList 加分组折叠、颜色标签

低优先级需求

# 需求 用户价值 复杂度 实现思路
N18 Key 详情对比 编辑前后 diff StringEditor/HashEditor 加 diff 视图
N19 命令收藏夹 常用命令快速调用 CliView 加收藏侧栏,localStorage 持久化
N20 连接 SSH 跳板机 多跳 SSH 场景 ssh2 隧道级联
N21 慢日志分析图表 趋势可视化 SlowLogView 加 ECharts 时间分布图
N22 快捷键体系完善 当前仅 5 个 加 Ctrl+F 搜索、Ctrl+1~9 切 tab、Ctrl+L 聚焦 CLI
N23 测试体系 当前无测试 Vitest 渲染进程单元测试;主进程 Redis 模块用 ioredis-mock
N24 CI/CD 自动化构建发布 GitHub Actions:lint+typecheck+build 三平台
N26 错误上报 收集崩溃信息 主进程 crashReporter + 渲染进程 errorHandler

三、路线图建议

第一阶段(高优先级):  N4 虚拟滚动 -> N5 Stream 完整化 -> N3 CLI 事务体验
第二阶段(中优先级):  N7 Cluster -> N9 导入导出 -> N11 大Key扫描 -> N13 PubSub视图
第三阶段(中优先级):  N8 ACL -> N10 Function -> N12 Latency -> N14 连接分组
第四阶段(低优先级):  N23 测试 -> N24 CI/CD -> N22 快捷键 -> N18-N21/N26

架构改进建议(伴随功能开发渐进推进)

  1. 资源管理:开发 N5/N13 时顺手引入 useDisposable composable,逐步迁移现有定时器/监听器
  2. 错误处理:开发 N9 时引入 safeInvoke 封装,统一 IPC 错误提示
  3. 类型安全:开发 N7/N8 时消除 connection.tsas any,定义完整的 Redis 操作类型
  4. 性能:N4 虚拟滚动是独立的高价值任务,建议优先单独开发