diff --git a/src/chongming_worker/runtime.py b/src/chongming_worker/runtime.py index 4d64ecf..168fe62 100644 --- a/src/chongming_worker/runtime.py +++ b/src/chongming_worker/runtime.py @@ -438,10 +438,14 @@ def resolve_runtime_config( cached = toml_cfg cache[key] = cached return {**config, **cached} - # toml(默认):toml 覆盖并修正缓存 - toml_cfg = dict(toml_cfg) - cache[key] = toml_cfg - return {**config, **toml_cfg} + # toml(默认):toml 仅作为「启动种子」。缓存缺失时写入; + # 缓存已存在(可能被运行时 config_set 更新过)则保留,不再用 toml 覆盖, + # 否则会丢掉前端/管理指令对内置插件(inline)写入的配置——即“改了不生效”。 + cached = cache.get(key) + if not isinstance(cached, dict): + cached = dict(toml_cfg) + cache[key] = cached + return {**config, **cached} def _merge_runtime_config(config: Dict[str, Any], updates: Dict[str, Any]) -> Dict[str, Any]: @@ -557,6 +561,8 @@ async def _handle_admin_command( # 写回改为缓存侧(不再回写 config.toml)。缓存为全局唯一事实来源, # 仅 index0 执行写+热重载,避免多副本并发 read-modify-write;其余副本只应用。 cache = getattr(controller, "cache", None) + # 记录旧值,便于热重载失败时回滚,避免缓存与运行配置不一致 + prev_section = _read_worker_config_section(cache, worker_type) if controller.index == 0: new_section = _persist_worker_config_section(cache, worker_type, updates) applied_updates = { @@ -576,11 +582,24 @@ async def _handle_admin_command( k: v for k, v in updates.items() if k not in CONFIG_FORBIDDEN_KEYS } - # 热重载:index0 副本触发插件重新初始化(重建客户端等),使新配置立即生效 + # 热重载:index0 副本触发插件重新初始化(重建客户端等),使新配置立即生效。 + # 若重建失败(如必填参数缺失),回滚缓存并中止重启——绝不带崩溃配置重启副本, + # 也避免缓存记录了一份实际未生效的配置。 if controller.index == 0 and controller.reload_cb is not None: - await controller.reload_cb( - _merge_runtime_config(config or {}, applied_updates) - ) + try: + await controller.reload_cb( + _merge_runtime_config(config or {}, applied_updates) + ) + except Exception as e: # noqa: BLE001 - 重建失败回滚一致状态 + if cache is not None: + cache[_configs_cache_key(worker_type)] = prev_section + logger.error( + "[Worker] %s 配置热重载失败,已回滚缓存并中止重启: %s", + worker_id, e, + ) + raise RuntimeError( + f"配置热重载失败,未重启(已回滚): {e}" + ) from e logger.info( "[Worker] %s 配置热重载完成,将以新配置重启", worker_id, )