第 29 篇
工程技术
在途任务遇到配置变更,如何拒绝过期结果
结合实际开发项目,讨论在途任务遇到配置变更,如何拒绝过期结果,说明设计理由、关键源码、验证方法及适用边界。
本文目录 · 7 节
本文属于 Memory Center:AI 编程上下文与记忆系统工程实践,第 29 篇,位于“可靠后台任务”模块。案例背景统一采用实际开发项目;复现步骤使用脱敏教学样例,不代表特定生产事故。
从实际问题出发
索引开始时使用模型甲,运行期间管理员改成模型乙。旧任务即使计算成功,其结果也不再满足最新设置;只检查进程退出码会错误发布过期结果。
配置修订是发布条件
任务应绑定开始时的配置或模型修订,发布时重新比较。项目级设置、模型档案和任务状态属于不同检查项,不能用一个笼统的“完成”标识代替。

图中展示的是本篇关注的职责和顺序。正常流程之外,还要结合下面的源码与实验检查失败分支;它不是对某次线上调用的运行时追踪。
冲突需要解释而非静默覆盖
拒绝旧结果会浪费已经完成的计算,但保住了当前系统语义。自动重试也可能重复制造成本,应把配置变化和重建要求展示给操作者。修改设置与启动新任务应按产品合同明确分开。
关键源码与阅读方法
源码基线为 Memory Center 6e90553(文档标注 5.0.0b24)。定位:memory_center/platform/store.py,函数 publish,起始行 110。
以下为源码节选,省略后续分支;不能作为独立脚本执行。
def publish(self, workspace_id, job_id, chunks, workspace_file, config_version):
with self.generation_lock(workspace_id), self.db.connection(True) as connection:
row = connection.execute("SELECT payload FROM records WHERE kind='job' AND id=?", (job_id,)).fetchone()
job = json.loads(row[0])
if job['status'] != 'running':
raise CatalogError('JOB_CANCELLED', '任务已取消,未发布索引')
if 'embedding_settings_revision' in job:
from memory_center.platform.project_embedding import embedding_settings
if embedding_settings(self, workspace_id)['revision'] != job['embedding_settings_revision']:
raise CatalogError('EMBEDDING_SETTINGS_CHANGED', '项目向量设置已改变,未发布索引,请重新提交任务')
from memory_center.platform.retrieval import index_terms
index_terms(connection, workspace_id, job_id, chunks)
for chunk in chunks:
connection.execute('INSERT INTO chunks VALUES(?,?,?,?,?,?,?,?)' if not self.db.url else
'''INSERT INTO chunks(id,workspace_id,generation,source_id,content,metadata,profile,embedding)
VALUES(?,?,?,?,?,?,?,?)''',
(chunk['id'], workspace_id, job_id, chunk['source_id'], chunk['content'],
json.dumps(chunk['metadata'], ensure_ascii=False), chunk.get('profile', ''),
json.dumps(chunk.get('embedding', []))))
if self.db.url and chunk.get('embedding'):
connection.execute('UPDATE chunks SET vector_value=?::vector WHERE id=?',
(str(chunk['embedding']), chunk['id']))
if self.db.url:
from collections import Counter
profiles = Counter((c.get('profile'), len(c.get('embedding', []))) for c in chunks)
for (profile, dimension), _count in profiles.items():
if profile and 0 < dimension <= 2000:
name = 'mc_vec_' + profile + '_' + str(dimension)
connection.execute(f"CREATE INDEX IF NOT EXISTS {name} ON chunks USING hnsw ((vector_value::vector({dimension})) vector_cosine_ops) WHERE profile='{profile}'")
index = {'id': workspace_id, 'workspace_id': workspace_id, 'generation': job_id,
'workspace_file': workspace_file, 'config_version': config_version, 'revision': 1,
'wiki_signature': job.get('wiki_signature', ''),
'code_coverage': job.get('code_coverage', {}),
'embedding_profile': job.get('embedding_profile', next((c.get('profile', '') for c in chunks if c.get('profile')), '')),
'embedding_mode': job.get('embedding_mode', 'all' if any(c.get('profile') for c in chunks) else 'off'),
'embedding_settings_revision': job.get('embedding_settings_revision', 0),
阅读时先找输入由谁提供,再区分纯计算、读取和写入;遇到异常或提前返回,追问调用方会得到什么,以及已有状态是否仍然有效。上面的代码只证明展示范围内的实现,跨模块行为应继续查看调用处和相应测试。
用一个小实验核对设计
建议在独立临时目录和隔离数据中操作,使用虚构的接口、文档与项目名称。
- 启动一个较慢的隔离索引。
- 在运行期间修改相关设置。
- 等待旧任务到达发布边界。
**要核对的结果:**旧配置结果应被拒绝,上一成功代际应继续有效,并给出可行动的重建说明。
可把观察记录为下表;没有执行的项写“未执行”,不能用设计预期冒充实测结果。
| 核对项 | 应保留的证据 |
|---|---|
| 使用条件 | 源码版本、配置、输入与项目范围 |
| 正常行为 | 实际返回、来源位置或状态变化 |
| 关键失败分支 | 错误码、可见结果与原状态是否保留 |
| 结论范围 | 已覆盖、未覆盖和需要进一步验证的条件 |
适用边界与继续阅读
本篇以静态源码与项目设计为依据,给出可执行的核对方法,未据此宣称已经完成新的性能或生产环境测试。不同版本的入口、默认值和底层实现可能变化,应先核对当前合同,再把方法用于自己的实际开发项目。
理解这一节后,可以回到专题总导航,沿同一模块继续阅读;顺序学习时使用专栏内的上一篇和下一篇。涉及具体技术选择,应连同本篇的代价与限制一起采用。