Periodic Scheduler: Dynamic Adjustment Strategies
In systems requiring periodic refresh of configurations, statistics, or caches, how do we design a scheduler that can dynamically adjust update intervals while gracefully handling errors? Today we analyze an industrial-grade Periodically Updated scheduler implementation.
The Core Problem
Traditional timed refresh mechanisms typically have fixed intervals, but in production environments:
- Normal operation requires longer intervals (reduce overhead)
- Errors require shorter intervals (fast recovery)
- Need to support runtime dynamic adjustment of refresh intervals
Design: Dual Duration + Error Recovery
class TPeriodicallyUpdated {
protected:
virtual bool UpdateImpl() = 0; // Subclass implements update logic
void SetReloadDuration(TDuration reloadDuration); // Dynamic adjustment
private:
TDuration mReloadDuration; // Normal refresh interval
TDuration mErrorReloadDuration; // Error refresh interval
TDuration mCheckPeriod; // Check interval
};
Core Mechanisms
Dual Duration Strategy:
- Normal case: uses longer interval
mReloadDuration - Error case: uses shorter interval
mErrorReloadDuration
- Normal case: uses longer interval
First Update Wait:
bool WaitForFirstUpdate(unsigned timeoutSeconds);Wait for first update to complete, ensuring system initialization
Error Recovery:
catch (yexception &ex) { mNextReloadTime = TInstant::Now() + mErrorReloadDuration; }
Trade-off Analysis
Advantages
- Dynamic Adjustment: Runtime modifiable refresh intervals
- Error Awareness: Auto-switch to fast recovery mode
- Thread Safe: Uses mutex + condition variable
Costs
- Thread Overhead: Independent background thread
- Complexity: Need to handle first update wait
- Resource Management: Requires explicit Stop() call
Clean Room Reimplementation: Rust Implementation
use std::sync::{Arc, Mutex, Condvar};
use std::time::{Duration, Instant};
use std::thread;
use std::sync::atomic::{AtomicBool, Ordering};
pub struct PeriodicallyUpdated<F>
where
F: FnMut() -> bool + Send + 'static,
{
reload_duration: Duration,
error_reload_duration: Duration,
check_period: Duration,
stopping: Arc<AtomicBool>,
updated: Arc<AtomicBool>,
updated_cond: Condvar,
next_reload_time: Mutex<Instant>,
updater: Option<thread::JoinHandle<()>>,
update_fn: Arc<Mutex<F>>,
}
impl<F> PeriodicallyUpdated<F>
where
F: FnMut() -> bool + Send + 'static,
{
pub fn new(
reload_duration: Duration,
error_reload_duration: Duration,
update_fn: F,
) -> Self {
// ...
}
pub fn start(&mut self) {
// Start background thread for periodic updates
}
pub fn wait_for_first_update(&self, timeout: Duration) -> bool {
// Wait for first update to complete
}
pub fn stop(&mut self) {
// Signal stop and join thread
}
}
Summary
The dynamic adjustment strategy of periodic update schedulers embodies the adaptive system design philosophy:
- Dual Duration Mode: Different intervals for normal and error states
- First Update Wait: Ensures initialization completes
- Error Recovery: Auto-switch to fast mode after exceptions
This design is particularly effective in configuration hot-reload, cache refresh, and similar scenarios.
Series: Arch (89/90)
View
▼