Skip to content

Commit 041d0c0

Browse files
authored
fix(cache): isolate cache entries across hot reloads (#45)
* fix(cache): isolate hot-reload cache generations * fix(cache): keep reload generations coherent
1 parent 811c528 commit 041d0c0

9 files changed

Lines changed: 650 additions & 61 deletions

File tree

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,9 @@ The DNS response cache uses the upstream response's minimum TTL, raised to min_t
522522

523523
When cache_background_refresh is enabled, entries near expiry can trigger an asynchronous refresh. A failed refresh leaves the existing entry in place. When serve_stale is enabled, an expired entry can be returned with serve_stale_ttl, subject to serve_stale_expire_ttl and serve_stale_client_timeout_ms.
524524

525-
The main configuration watcher reloads a valid JSON file and clears the rule cache. Invalid reloads leave the previous configuration active. The listener addresses, UDP worker count, TLS DoH listener, connection-pool construction, cache construction, and other Engine initialization settings are created at startup; changing those settings should be followed by a restart.
525+
The main configuration watcher reloads a valid JSON file using per-pipeline cache namespaces. A changed pipeline immediately stops addressing response-cache, rule-cache, and in-flight entries created by its previous configuration; an unchanged pipeline keeps its warm caches. A change to global settings rotates every pipeline namespace. Old namespace entries are not synchronously deleted and remain bounded by the existing cache capacity and TTL policies. Each request, including background refresh and response-phase jumps, keeps the configuration snapshot that selected its namespace, so work started before a reload cannot write into the active generation. Invalid reloads leave the previous configuration active.
526+
527+
The listener addresses, UDP worker count, TLS DoH listener, connection-pool construction, cache construction, and other Engine initialization settings are created at startup; changing those settings should be followed by a restart.
526528

527529
GeoSite files in geosite_data_paths are watched and reloaded. GeoIP files supplied through geoip_dat_path are watched and reloaded. A GeoIP MMDB supplied through geoip_db_path is loaded at startup; the current watcher is for geoip_dat_path, not the MMDB path.
528530

README.zh-CN.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,9 @@ DNS 响应缓存使用上游响应的最小 TTL;配置 min_ttl 时会将其提
521521

522522
启用 cache_background_refresh 后,接近过期的条目可以触发异步刷新;刷新失败会保留现有条目。启用 serve_stale 后,可以返回过期条目,并使用 serve_stale_ttl 作为响应 TTL,同时受 serve_stale_expire_ttl 和 serve_stale_client_timeout_ms 限制。
523523

524-
主配置 watcher 会重载有效 JSON 并清空规则缓存。无效的重载会保留旧配置。监听地址、UDP worker 数量、TLS DoH 监听器、连接池构造、缓存构造和其他 Engine 初始化参数均在启动时创建;修改这些设置后应重启服务。
524+
主配置 watcher 使用按 Pipeline 划分的缓存命名空间重载有效 JSON。发生变化的 Pipeline 会立即停止访问旧配置产生的响应缓存、规则缓存和进行中请求;未变化的 Pipeline 会保留热缓存。任意全局设置变化都会轮换所有 Pipeline 的缓存命名空间。旧命名空间中的条目不会被同步删除,而是继续受现有缓存容量和 TTL 策略限制。包括后台刷新和响应阶段跳转在内,每个请求都会保持选择其缓存命名空间时的配置快照,因此重载前启动的任务无法写入当前生效的缓存代际。无效的重载会保留旧配置。
525+
526+
监听地址、UDP worker 数量、TLS DoH 监听器、连接池构造、缓存构造和其他 Engine 初始化参数均在启动时创建;修改这些设置后应重启服务。
525527

526528
geosite_data_paths 中的 GeoSite 文件会被监控并重载。geoip_dat_path 指定的 GeoIP 文件会被监控并重载。geoip_db_path 指定的 MMDB 在启动时加载;当前 watcher 监控的是 geoip_dat_path,不是 MMDB 路径。
527529

src/engine/core.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::matcher::geosite::GeoSiteManager;
2020
use super::concurrency::{FlowControlState, PermitManager};
2121
use super::rules::RuleCacheEntry;
2222
use super::transport::{DohClient, DoqClient, DotMultiplexer, TcpMultiplexer, UdpClient};
23-
use super::types::{EngineInner, InflightMap};
23+
use super::types::{EngineInner, InflightMap, build_cache_namespaces};
2424

2525
#[derive(Clone)]
2626
pub struct Engine {
@@ -169,6 +169,7 @@ impl Engine {
169169
.collect();
170170

171171
let state = Arc::new(ArcSwap::from_pointee(EngineInner {
172+
cache_namespaces: build_cache_namespaces(&cfg),
172173
pipeline: cfg,
173174
compiled_pipelines: compiled,
174175
pipeline_index,

0 commit comments

Comments
 (0)