0.34.6_repo_cleanup
This commit is contained in:
1 parent
ce1a90397c
commit
133d2f0f91
273 files changed
+5969
-6926
No files matched your search
@@ -1,16 +1,8 @@
|
||||
impl App {
|
||||
/// Re-read configured public certificate/key files and publish a new
|
||||
/// immutable TLS/routing snapshot without changing desired configuration
|
||||
/// or its SQLite revision. Existing connections continue on their current
|
||||
/// TLS session; new H1/H2/H3 handshakes use the refreshed certificates.
|
||||
pub async fn reload_certificates(self: &Arc<Self>) -> Result<u64, ApiError> {
|
||||
self.reload_certificate_snapshot(None).await
|
||||
}
|
||||
|
||||
/// Reload an externally managed/manual certificate by id. The immutable TLS
|
||||
/// resolver is rebuilt as one validated snapshot, so the requested pair is
|
||||
/// re-read atomically with the other configured pairs while desired
|
||||
/// configuration and its revision remain unchanged.
|
||||
pub async fn reload_certificate(
|
||||
self: &Arc<Self>,
|
||||
certificate_id: &str,
|
||||
|
||||
@@ -214,9 +214,6 @@ impl App {
|
||||
Arc::downgrade(&app),
|
||||
app.shutdown.clone(),
|
||||
));
|
||||
// High request rates create short-lived allocations in Hyper/Tokio and
|
||||
// cache fill paths. glibc may retain already-free arenas as RSS. Trim
|
||||
// them periodically without evicting live cache objects or connections.
|
||||
let trim_shutdown = app.shutdown.clone();
|
||||
let trim_app = Arc::downgrade(&app);
|
||||
app.tunnels.spawn(async move {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
impl App {
|
||||
/// Rebuild only the effective routing snapshot from the latest Docker observations.
|
||||
/// Desired configuration and its SQLite revision remain unchanged.
|
||||
pub async fn reconcile_docker(self: &Arc<Self>) -> Result<(), ApiError> {
|
||||
let _lock = self.update_lock.lock().await;
|
||||
let previous = self.config.load_full();
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
//! Explicit JSON configuration backing file. SQLite remains the revision/audit journal.
|
||||
//! File replacement is atomic on the containing filesystem and refuses symlink targets.
|
||||
use crate::config::{Config, MAX_CONFIG_BYTES};
|
||||
use anyhow::{bail, ensure, Context, Result};
|
||||
use sha2::{Digest, Sha256};
|
||||
@@ -39,8 +37,6 @@ pub fn read(path: &Path) -> Result<(Config, Fingerprint)> {
|
||||
Ok((config, Sha256::digest(&contents).into()))
|
||||
}
|
||||
|
||||
// Only compare fingerprints of bytes, never raw secrets in logs. Caller serializes
|
||||
// saves under App::update_lock; conflicts with out-of-band file edits fail closed.
|
||||
pub fn save(path: &Path, expected: Fingerprint, config: &Config) -> Result<Fingerprint> {
|
||||
let (_, actual) = read(path)?;
|
||||
if actual != expected {
|
||||
@@ -73,7 +69,6 @@ pub fn save(path: &Path, expected: Fingerprint, config: &Config) -> Result<Finge
|
||||
let mut file = options.open(&temp)?;
|
||||
file.write_all(&bytes)?;
|
||||
file.sync_all()?;
|
||||
// An external writer may have changed the source while the temp was prepared.
|
||||
if read(path)?.1 != expected {
|
||||
bail!("configuration file changed during save");
|
||||
}
|
||||
|
||||
@@ -87,8 +87,6 @@ mod cache_revision_tests {
|
||||
} else {
|
||||
protocol_only.vhosts[0].http3_enabled = !base.vhosts[0].http3_enabled;
|
||||
}
|
||||
// The effective configuration really changes, but the cache key
|
||||
// does not. This must hold for both toggling directions.
|
||||
assert_ne!(
|
||||
(protocol_only.vhosts[0].http2_enabled, protocol_only.vhosts[0].http3_enabled),
|
||||
(base.vhosts[0].http2_enabled, base.vhosts[0].http3_enabled),
|
||||
@@ -144,7 +142,6 @@ mod cache_revision_tests {
|
||||
let affected_id = base.vhosts[0].id.clone();
|
||||
assert!(matches!(cache_invalidation(&base, &vhost), CacheInvalidation::Scopes(ids) if ids == vec![affected_id]));
|
||||
|
||||
// A content change must not invalidate another independent vhost.
|
||||
let mut multiple = base.clone();
|
||||
let mut another = multiple.vhosts[0].clone();
|
||||
another.id = "other-scope".into();
|
||||
|
||||
@@ -83,14 +83,10 @@ enum CacheInvalidation {
|
||||
Scopes(Vec<String>),
|
||||
}
|
||||
|
||||
/// Global compatibility identity for HOT/COLD cache entries. Vhost-specific
|
||||
/// representation changes use individual scope generations and COLD fingerprints.
|
||||
/// Connection-pool/LB knobs do not enter either identity.
|
||||
fn cache_revision(config: &config::Config) -> u64 {
|
||||
let mut cache = config.cache.clone();
|
||||
cache.memory_preset = None;
|
||||
cache.cold_preset = None;
|
||||
// These are request admission or response diagnostics, never stored objects.
|
||||
cache.bypass_query = false;
|
||||
cache.bypass_prefixes.clear();
|
||||
cache.http_invalidation_allowed_cidrs.clear();
|
||||
@@ -104,11 +100,8 @@ fn cache_revision(config: &config::Config) -> u64 {
|
||||
transform.preset = None;
|
||||
transform.memory_budget_bytes = 0;
|
||||
transform.max_inflight = 0;
|
||||
// Web services and FPM profiles can change the bytes served by a location.
|
||||
// Until their dependency graph is split into scopes, invalidate globally.
|
||||
let mut web_services = config.web_services.clone();
|
||||
for service in &mut web_services {
|
||||
// Kernel write strategy never changes the HTTP representation.
|
||||
service.sendfile = crate::web_server::SendfileMode::Off;
|
||||
}
|
||||
cache_digest(&(
|
||||
@@ -127,8 +120,6 @@ fn cache_digest<T: serde::Serialize>(value: &T) -> u64 {
|
||||
u64::from_be_bytes(digest[..8].try_into().expect("sha256 prefix"))
|
||||
}
|
||||
|
||||
/// Only effective origin/content policies contribute to this scope identity.
|
||||
/// A vhost keepalive or load-balancer control save must retain both cache tiers.
|
||||
fn vhost_cache_revision(vhost: &crate::vhost::Vhost) -> u64 {
|
||||
let mut view = vhost.clone();
|
||||
view.websockets = false;
|
||||
@@ -159,9 +150,6 @@ fn vhost_cache_revision(vhost: &crate::vhost::Vhost) -> u64 {
|
||||
view.proxy_timeouts = Default::default();
|
||||
view.frontend.listener_ids.clear();
|
||||
view.cache.expose_only_hits = None;
|
||||
// The complete LB policy (keepalive, recycling, weights, retries, health,
|
||||
// affinity and queues) governs connection selection, not cache identity.
|
||||
// Sticky authentication checks and bypass still run before the cache lookup.
|
||||
view.load_balancing = Default::default();
|
||||
for member in &mut view.backends {
|
||||
member.weight = 1;
|
||||
@@ -196,8 +184,6 @@ fn cache_invalidation(previous: &config::Config, next: &config::Config) -> Cache
|
||||
.filter(|(id, revision)| new.get(*id) != Some(*revision))
|
||||
.map(|(id, _)| id.clone())
|
||||
.collect();
|
||||
// New scopes do not have previous cache objects, but include the set for
|
||||
// completeness if an ID is ever reused within a single config transaction.
|
||||
changed.extend(new.keys().filter(|id| !old.contains_key(*id)).cloned());
|
||||
changed.sort();
|
||||
changed.dedup();
|
||||
|
||||
@@ -7,8 +7,6 @@ impl App {
|
||||
*self.config_file.lock().await = Some((path, hash));
|
||||
}
|
||||
|
||||
/// Reads an operator-edited JSON file and publishes it through the same
|
||||
/// validation, history and hot-apply path as a panel save.
|
||||
pub async fn reload_from_file(
|
||||
self: &Arc<Self>,
|
||||
expected_revision: u64,
|
||||
@@ -71,11 +69,9 @@ impl App {
|
||||
));
|
||||
}
|
||||
|
||||
/// Drain detached writers after the listeners and their handlers have stopped.
|
||||
pub async fn drain_updates(&self) {
|
||||
let _all_slots = self.update_slots.clone().acquire_many_owned(8).await;
|
||||
}
|
||||
/// The detached task completes persistence + publication even if the HTTP caller disconnects.
|
||||
pub async fn update(self: &Arc<Self>, update: Update) -> Result<config::Envelope, ApiError> {
|
||||
self.update_as(update, "local".into()).await
|
||||
}
|
||||
@@ -161,9 +157,6 @@ impl App {
|
||||
"configuration changed; reload before saving".into(),
|
||||
));
|
||||
}
|
||||
// Explicit --config is the source of truth. A panel save writes the
|
||||
// JSON file before recording its revision in SQLite, while a manual
|
||||
// reload imports the operator-edited file without overwriting it.
|
||||
let file_updated_hash =
|
||||
if let Some((path, last_hash)) = this.config_file.lock().await.as_ref().cloned() {
|
||||
let config = prepared.envelope.config.clone();
|
||||
@@ -212,8 +205,6 @@ impl App {
|
||||
}
|
||||
};
|
||||
if !matches!(&persisted, Ok(true)) {
|
||||
// The database commit failed. Best-effort file rollback only
|
||||
// for saves (never for an operator-authored manual reload).
|
||||
if reload_hash.is_none() {
|
||||
if let Some((path, _, new_hash)) = &file_updated_hash {
|
||||
let path = path.clone();
|
||||
@@ -226,7 +217,6 @@ impl App {
|
||||
.await
|
||||
{
|
||||
Ok(Ok(restored_hash)) => {
|
||||
// The old document may be reformatted, so use its new fingerprint.
|
||||
*this.config_file.lock().await = Some((path, restored_hash));
|
||||
}
|
||||
result => tracing::error!(
|
||||
@@ -254,12 +244,7 @@ impl App {
|
||||
if let Some((path, _, new_hash)) = file_updated_hash.as_ref() {
|
||||
*this.config_file.lock().await = Some((path.clone(), *new_hash));
|
||||
}
|
||||
// No await between successful commit and publication. Cache identity is
|
||||
// intentionally decoupled from the configuration revision, so unrelated
|
||||
// control-plane saves do not invalidate hot/cold objects.
|
||||
let envelope = prepared.envelope.clone();
|
||||
// After commit, reject late cache tickets from the old routing
|
||||
// snapshot before any scope purge. Existing unaffected objects stay.
|
||||
this.cache.set_control_revision(envelope.revision);
|
||||
match invalidation {
|
||||
CacheInvalidation::All(cache_revision) => {
|
||||
@@ -272,9 +257,6 @@ impl App {
|
||||
}
|
||||
CacheInvalidation::None => {}
|
||||
}
|
||||
// A COLD entry is usable after restart only if its scope still has
|
||||
// the same origin/content policy. Publish the fingerprints after
|
||||
// the cache generation barriers but before the routing snapshot.
|
||||
this.cache
|
||||
.replace_scope_revisions(vhost_cache_revisions(&envelope.config));
|
||||
this.cache.configure(envelope.config.cache.clone());
|
||||
|
||||
Reference in new issue
Block a user