Skip to content

fix:后端同步时保留仓库本地元数据#147

Merged
AmintaCCCP merged 1 commit into
AmintaCCCP:mainfrom
hych0317:fix-preserve-ai-metadata
May 18, 2026
Merged

fix:后端同步时保留仓库本地元数据#147
AmintaCCCP merged 1 commit into
AmintaCCCP:mainfrom
hych0317:fix-preserve-ai-metadata

Conversation

@hych0317
Copy link
Copy Markdown
Contributor

@hych0317 hych0317 commented May 17, 2026

变更说明

修复后端同步仓库列表时,本地已有的仓库级元数据被覆盖的问题。

当前自动同步从后端拉取 repositories 后会直接调用 setRepositories(backendRepos),如果后端返回的仓库对象缺少本地已有字段,会导致已完成的 AI 分析信息丢失,例如:

  • ai_summary
  • ai_tags
  • ai_platforms
  • analyzed_at
  • analysis_failed

本次修改在后端仓库列表写入本地 store 前,对同一 repo.id 的仓库进行合并:仍以后端返回的仓库信息为基础,但保留本地已有的 AI 分析字段和仓库级本地元数据。

保留的本地字段

  • AI 分析信息
  • 自定义描述、标签、分类
  • 分类锁定状态
  • 最近编辑时间
  • release 同步状态

行为说明

  • 后端返回的仓库列表仍然是权威列表
  • 新增 star 的仓库会正常加入
  • 已不在后端返回列表中的仓库不会被本地数据恢复
  • 不修改 AI 配置、WebDAV 配置、登录信息、主题等用户配置同步逻辑

验证

已在windows本地进行覆盖安装验证,由于mac不在身边,麻烦你来验证了

Summary by CodeRabbit

  • Bug Fixes
    • Fixed synchronization to preserve local repository metadata—including custom descriptions, tags, analysis status, and other user-created data—when syncing updates from the backend, preventing unintended data loss during sync operations.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 17, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6c453a39-1562-4b1d-b8d6-de87be822450

📥 Commits

Reviewing files that changed from the base of the PR and between fee0908 and 5c92265.

📒 Files selected for processing (2)
  • src/services/autoSync.ts
  • src/utils/repositoryMerge.ts

📝 Walkthrough

Walkthrough

This PR introduces repository metadata preservation during backend synchronization. A new merge utility selectively preserves local metadata fields when updating repositories from the backend, replacing direct overwrite logic in the auto-sync service to prevent loss of local AI summaries, tags, custom descriptions, and related metadata.

Changes

Repository Metadata Sync Preservation

Layer / File(s) Summary
Repository merge utility
src/utils/repositoryMerge.ts
mergeRepositoriesPreservingLocalMetadata function preserves defined local metadata fields (timestamps, summaries, tags, categories, lock flags) when merging with backend repositories by checking local values and copying them only when defined.
Backend sync integration
src/services/autoSync.ts
Import of the merge utility and its application in syncFromBackend to merge backend repositories with local state instead of direct overwrite.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • AmintaCCCP/GithubStarsManager#142: Both PRs modify src/services/autoSync.ts's syncFromBackend to change how backend repository results are applied to the Zustand store by preserving local repositories/metadata instead of overwriting them directly.

Poem

🐰 A rabbit hops through sync and merge,
Preserving memories from the surge,
Local metadata, safe and sound,
Where backend updates and locals are bound,
With care, the states now gently blend! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: preserving local repository metadata during backend synchronization, which is the core purpose of this PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Owner

@AmintaCCCP AmintaCCCP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Code Review: fix: 后端同步时保留仓库本地元数据

审计人: Hermes Agent
审计模型: z-ai/glm-5.1
CI 状态: ✅ 全部通过 (macOS / Ubuntu / Windows)
TypeScript 编译:tsc --noEmit 无错误


✅ Looks Good

  • 核心思路正确:后端是仓库列表的权威来源,本地仅保护「后端不存的本地专属字段」,语义清晰
  • 新增文件职责单一repositoryMerge.ts 只做一件事——merge local metadata,命名清晰
  • LOCAL_REPOSITORY_FIELDSkeyof Repository 约束:TypeScript 编译器保证字段名与类型定义同步,未来加新字段时类型会帮忙
  • localValue !== undefined 的守卫:避免将本地的 undefined 覆盖后端本有值的情况(尤其对 analysis_failed: false 很重要)
  • Map 查找 O(1):对仓库列表的规模完全合理
  • isBootstrapEmpty 分支不受影响:首同步时空后端走 push 逻辑,不会误触发 merge
  • CI 三平台构建均通过:无回归

⚠️ Warnings (2)

  1. subscribed_to_releases 字段遗漏

    • Repository 类型中 subscribed_to_releases?: boolean (L25) 是本地 UI 设置的订阅标记
    • RepositoryList.tsx:775ReleaseTimeline.tsx:507 中由用户操作本地写入
    • 但未列入 LOCAL_REPOSITORY_FIELDS,后端同步时会丢失
    • 建议加入:
      'subscribed_to_releases',
  2. 合并后 _lastHash.repos 基于后端原始数据,但 store 中已混入本地字段

    • autoSync.ts:144_lastHash.repos = hashes.repos — 这里的 hashes.reposquickHash(backendRepos),即后端原始数据的哈希
    • 但实际写入 store 的是 merge 后的数据(含本地字段),下次 syncToBackend_lastHash.repos = quickHash(state.repositories) 用的是合并后的数据
    • 场景:用户 A 完成分析 → push 到后端 → 后端存了 ai_summary → 用户 B pull 时 merge 保留 → B push 时后端也有 ai_summary此时没问题
    • 但如果后端不持久化这些本地字段(SQLite 可能 ignore unknown columns),pull 回来的数据永远不含本地字段 → hash 始终不同 → 每次 poll 都会触发 setRepositories → 合并后的 store 引用变了 → 触发 push → 5s 后又 pull… 形成不必要的写循环
    • 严重程度:中。数据不会丢(merge 每次都保护),但造成了多余的 store 更新和 push 操作。建议把 hash 改为对 merge 后的数据计算:
      const merged = mergeRepositoriesPreservingLocalMetadata(backendRepos, localRepos);
      _lastHash.repos = quickHash(merged);
      state.setRepositories(merged);

💡 Suggestions (2)

  1. starred_at 字段是否需要保留?

    • starred_at 是从 GitHub API 返回的,后端 fetchRepositories 是否保留此字段取决于后端 SQLite schema。如果后端不存该字段,pull 后 starred_at 丢失,影响按 starred 时间排序(SearchBar.tsx:428)。建议确认后端是否持久化 starred_at,如果不存则加入保留列表。
  2. as Record<keyof Repository, unknown> 类型断言可简化

    • 当前 mergedRepository 已经是 Repository 类型,LOCAL_REPOSITORY_FIELDSArray<keyof Repository>,直接赋值 mergedRepository[field] = localValue 在严格模式下会因类型不统一报错。断言合理,但可以改为:
      const mergedRepository = { ...incomingRepository } as Record<string, unknown>;
      更直观,语义上是「可写的字典」,不需要 Record<keyof Repository, unknown> 那么精确。

审计总结

类别 数量
🔴 Critical 0
⚠️ Warning 2
💡 Suggestion 2

结论:Comment — 两个 Warning 都不阻塞合并(数据不会丢失),但建议尽快补充 subscribed_to_releases 字段,并评估 hash 循环写问题。功能逻辑正确,代码整洁,CI 全绿。


Reviewed by Hermes Agent (z-ai/glm-5.1)

@AmintaCCCP AmintaCCCP merged commit 5d8e1e0 into AmintaCCCP:main May 18, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants