v0.26.4
This commit is contained in:
1 parent
cf25423dde
commit
52cc137c73
50 files changed
+410
-172
No files matched your search
+35
-5
@@ -103,6 +103,11 @@ impl ProxyClient {
|
||||
pub fn rotation_stats(&self) -> ClientRotationStats {
|
||||
self.inner.stats()
|
||||
}
|
||||
|
||||
/// Recycle an aged connection pool even when no user request arrives.
|
||||
pub(crate) fn maintain_rotation(&self) {
|
||||
self.inner.maintain_rotation();
|
||||
}
|
||||
}
|
||||
|
||||
impl RotatingClient {
|
||||
@@ -136,12 +141,36 @@ impl RotatingClient {
|
||||
.pool_recycle_seconds
|
||||
.saturating_mul(1_000);
|
||||
if request_due || age_due {
|
||||
self.rotate(observed_generation, if request_due { "requests" } else { "age" });
|
||||
self.rotate(
|
||||
observed_generation,
|
||||
if request_due { "requests" } else { "age" },
|
||||
true,
|
||||
);
|
||||
}
|
||||
self.current.load_full()
|
||||
}
|
||||
|
||||
fn rotate(&self, observed_generation: u64, reason: &'static str) {
|
||||
fn maintain_rotation(&self) {
|
||||
self.maintain_rotation_at(monotonic_millis());
|
||||
}
|
||||
|
||||
fn maintain_rotation_at(&self, now_ms: u64) {
|
||||
let recycle_seconds = self.factory.keepalive.pool_recycle_seconds;
|
||||
if recycle_seconds == 0 {
|
||||
return;
|
||||
}
|
||||
let age_ms = now_ms.saturating_sub(self.generation_started_ms.load(Ordering::Relaxed));
|
||||
if age_ms >= recycle_seconds.saturating_mul(1_000) {
|
||||
self.rotate(self.generation.load(Ordering::Acquire), "age", false);
|
||||
}
|
||||
}
|
||||
|
||||
fn rotate(
|
||||
&self,
|
||||
observed_generation: u64,
|
||||
reason: &'static str,
|
||||
triggering_request: bool,
|
||||
) {
|
||||
if self.generation.load(Ordering::Acquire) != observed_generation
|
||||
|| self
|
||||
.rotating
|
||||
@@ -159,9 +188,10 @@ impl RotatingClient {
|
||||
Ok(client) => {
|
||||
let next_generation = observed_generation.saturating_add(1);
|
||||
self.current.store(Arc::new(client));
|
||||
// The request that triggered the swap is sent through the new
|
||||
// generation after rotate() returns, so count it there.
|
||||
self.generation_requests.store(1, Ordering::Relaxed);
|
||||
// Request-driven rotation sends the triggering request through
|
||||
// the new generation. Maintenance-driven rotation happens idle.
|
||||
self.generation_requests
|
||||
.store(if triggering_request { 1 } else { 0 }, Ordering::Relaxed);
|
||||
self.generation_started_ms
|
||||
.store(monotonic_millis(), Ordering::Relaxed);
|
||||
self.generation.store(next_generation, Ordering::Release);
|
||||
|
||||
@@ -34,6 +34,33 @@ mod tests {
|
||||
assert_eq!(stats.generation, 1);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn generation_recycles_after_age_without_request() {
|
||||
let backend = backend("rotation-age-test", 18083);
|
||||
let mut keepalive = crate::balance::Keepalive::default();
|
||||
keepalive.pool_recycle_requests = 0;
|
||||
keepalive.pool_recycle_seconds = 1;
|
||||
let client = client_with_keepalive(
|
||||
&backend,
|
||||
AddressPolicy::new(&backend).unwrap(),
|
||||
false,
|
||||
&keepalive,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
client
|
||||
.inner
|
||||
.generation_started_ms
|
||||
.store(10, std::sync::atomic::Ordering::Relaxed);
|
||||
client.inner.maintain_rotation_at(2_010);
|
||||
|
||||
let stats = client.rotation_stats();
|
||||
assert_eq!(stats.rotations, 1);
|
||||
assert_eq!(stats.generation, 1);
|
||||
assert_eq!(stats.generation_requests, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generation_recycling_can_be_disabled() {
|
||||
let backend = backend("rotation-off", 18082);
|
||||
|
||||
Reference in new issue
Block a user