|
@@ -158,11 +158,25 @@ def _format_article_item(a: dict) -> dict:
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+# 同步互斥锁:防止定时任务与手动触发并发写同一 Chroma collection。
|
|
|
|
|
+# gunicorn 单 worker 单事件循环下 asyncio.Lock 足够;两任务并发曾导致
|
|
|
|
|
+# microbiome 块被相互删除(缺 844 块),加锁后后到者直接跳过。
|
|
|
|
|
+_sync_lock = asyncio.Lock()
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
async def sync_knowledge_base():
|
|
async def sync_knowledge_base():
|
|
|
"""同步三个数据源: article/microbiome/dan_knowledge 全量重建到 cfc_knowledge。
|
|
"""同步三个数据源: article/microbiome/dan_knowledge 全量重建到 cfc_knowledge。
|
|
|
|
|
|
|
|
- 每源独立失败隔离;全部成功后更新 .sync_state 记录 last_sync。
|
|
|
|
|
|
|
+ 加并发锁(后到者跳过);每源独立失败隔离;全部成功后更新 .sync_state。
|
|
|
"""
|
|
"""
|
|
|
|
|
+ if _sync_lock.locked():
|
|
|
|
|
+ logger.info("已有知识库同步任务进行中,本次触发跳过")
|
|
|
|
|
+ return
|
|
|
|
|
+ async with _sync_lock:
|
|
|
|
|
+ await _do_sync()
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+async def _do_sync():
|
|
|
loader = KnowledgeLoader()
|
|
loader = KnowledgeLoader()
|
|
|
splitter = get_knowledge_splitter()
|
|
splitter = get_knowledge_splitter()
|
|
|
embeddings = get_embeddings()
|
|
embeddings = get_embeddings()
|