v0.12.0-preety_code
This commit is contained in:
+65
-18
@@ -1,8 +1,14 @@
|
||||
fn reset_temporary_condition_observations_after_restart(state: &AppState) -> Result<usize, AppError> {
|
||||
fn reset_temporary_condition_observations_after_restart(
|
||||
state: &AppState,
|
||||
) -> Result<usize, AppError> {
|
||||
let mut changed = 0usize;
|
||||
for mut zone in state.db.list_zones()? {
|
||||
let Some(session) = zone.temporary_quick_thermostat.as_mut() else { continue; };
|
||||
if session.condition_started_at.is_none() && session.condition_last_observed_at.is_none() { continue; }
|
||||
let Some(session) = zone.temporary_quick_thermostat.as_mut() else {
|
||||
continue;
|
||||
};
|
||||
if session.condition_started_at.is_none() && session.condition_last_observed_at.is_none() {
|
||||
continue;
|
||||
}
|
||||
session.condition_started_at = None;
|
||||
session.condition_last_observed_at = None;
|
||||
zone.updated_at = Utc::now();
|
||||
@@ -24,13 +30,23 @@ pub fn start(state: AppState) {
|
||||
loop {
|
||||
match poll_all(&poll_state).await {
|
||||
Ok(()) => {
|
||||
if !poll_state.initial_device_sync_complete.swap(true, Ordering::AcqRel) {
|
||||
tracing::info!("initial device state synchronized; thermostat control enabled");
|
||||
if !poll_state
|
||||
.initial_device_sync_complete
|
||||
.swap(true, Ordering::AcqRel)
|
||||
{
|
||||
tracing::info!(
|
||||
"initial device state synchronized; thermostat control enabled"
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => tracing::error!(error=?err, "device poll cycle failed"),
|
||||
}
|
||||
let seconds = poll_state.settings.read().await.poll_interval_seconds.max(2);
|
||||
let seconds = poll_state
|
||||
.settings
|
||||
.read()
|
||||
.await
|
||||
.poll_interval_seconds
|
||||
.max(2);
|
||||
sleep(Duration::from_secs(seconds)).await;
|
||||
}
|
||||
});
|
||||
@@ -42,7 +58,10 @@ pub fn start(state: AppState) {
|
||||
// A restart must never make decisions from the persisted, potentially stale
|
||||
// device snapshot. Wait for one full live poll before thermostat/schedule/automation
|
||||
// ownership can emit commands. Manual API/remote control remains available.
|
||||
if !control_state.initial_device_sync_complete.load(Ordering::Acquire) {
|
||||
if !control_state
|
||||
.initial_device_sync_complete
|
||||
.load(Ordering::Acquire)
|
||||
{
|
||||
sleep(Duration::from_millis(250)).await;
|
||||
continue;
|
||||
}
|
||||
@@ -52,7 +71,12 @@ pub fn start(state: AppState) {
|
||||
if let Err(err) = run_automations(&control_state).await {
|
||||
tracing::error!(error=?err, "automation cycle failed");
|
||||
}
|
||||
let seconds = control_state.settings.read().await.zone_interval_seconds.max(2);
|
||||
let seconds = control_state
|
||||
.settings
|
||||
.read()
|
||||
.await
|
||||
.zone_interval_seconds
|
||||
.max(2);
|
||||
let normal_delay = Duration::from_secs(seconds);
|
||||
let resume_delay = match next_zone_control_deadline_delay(&control_state) {
|
||||
Ok(value) => value,
|
||||
@@ -61,7 +85,9 @@ pub fn start(state: AppState) {
|
||||
None
|
||||
}
|
||||
};
|
||||
let sleep_for = resume_delay.map(|delay| delay.min(normal_delay)).unwrap_or(normal_delay);
|
||||
let sleep_for = resume_delay
|
||||
.map(|delay| delay.min(normal_delay))
|
||||
.unwrap_or(normal_delay);
|
||||
tokio::select! {
|
||||
_ = sleep(sleep_for) => {},
|
||||
_ = control_state.zone_control_wakeup.notified() => {},
|
||||
@@ -76,7 +102,11 @@ pub fn start(state: AppState) {
|
||||
let settings = maintenance_state.settings.read().await.clone();
|
||||
// When InfluxDB is enabled, compact all locally retained legacy history before
|
||||
// transferring old buckets. Without Influx, compact only the configured retention window.
|
||||
let compaction_days = if settings.influxdb.enabled { 3650 } else { settings.history_retention_days.max(1) } as i64;
|
||||
let compaction_days = if settings.influxdb.enabled {
|
||||
3650
|
||||
} else {
|
||||
settings.history_retention_days.max(1)
|
||||
} as i64;
|
||||
if settings.history_compaction_enabled {
|
||||
match maintenance_state.db.compact_history(compaction_days) {
|
||||
Ok(count) if count > 0 => tracing::info!(count, "history samples compacted"),
|
||||
@@ -85,22 +115,36 @@ pub fn start(state: AppState) {
|
||||
}
|
||||
}
|
||||
if settings.influxdb.enabled {
|
||||
match archive_old_history(&maintenance_state, settings.influxdb.history_threshold_days.max(1)).await {
|
||||
Ok(count) if count > 0 => tracing::info!(count, "old local readings archived to InfluxDB and removed from SQLite"),
|
||||
match archive_old_history(
|
||||
&maintenance_state,
|
||||
settings.influxdb.history_threshold_days.max(1),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(count) if count > 0 => tracing::info!(
|
||||
count,
|
||||
"old local readings archived to InfluxDB and removed from SQLite"
|
||||
),
|
||||
Ok(_) => {}
|
||||
Err(err) => tracing::warn!(error=?err, "cannot archive old history to InfluxDB; SQLite copies were kept"),
|
||||
Err(err) => {
|
||||
tracing::warn!(error=?err, "cannot archive old history to InfluxDB; SQLite copies were kept")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let retention_days = settings.history_retention_days.max(1) as i64;
|
||||
match maintenance_state.db.prune_readings(retention_days) {
|
||||
Ok(count) if count > 0 => tracing::info!(count, retention_days, "old local readings pruned"),
|
||||
Ok(count) if count > 0 => {
|
||||
tracing::info!(count, retention_days, "old local readings pruned")
|
||||
}
|
||||
Ok(_) => {}
|
||||
Err(err) => tracing::warn!(error=?err, "cannot prune readings"),
|
||||
}
|
||||
}
|
||||
let event_retention_days = settings.event_log_retention_days.max(1) as i64;
|
||||
match maintenance_state.db.prune_events(event_retention_days) {
|
||||
Ok(count) if count > 0 => tracing::info!(count, event_retention_days, "old event log rows pruned"),
|
||||
Ok(count) if count > 0 => {
|
||||
tracing::info!(count, event_retention_days, "old event log rows pruned")
|
||||
}
|
||||
Ok(_) => {}
|
||||
Err(err) => tracing::warn!(error=?err, "cannot prune event log"),
|
||||
}
|
||||
@@ -117,12 +161,15 @@ async fn archive_old_history(state: &AppState, threshold_days: u32) -> Result<u6
|
||||
// Successful batches are deleted from SQLite, so the next pass naturally continues forward.
|
||||
for _ in 0..50 {
|
||||
let (devices, zones, ha) = state.db.history_before(cutoff, 1_000)?;
|
||||
if devices.is_empty() && zones.is_empty() && ha.is_empty() { break; }
|
||||
if devices.is_empty() && zones.is_empty() && ha.is_empty() {
|
||||
break;
|
||||
}
|
||||
influxdb::write_batch(&state.http, &settings, &devices, &zones, &ha).await?;
|
||||
let deleted = state.db.delete_history_batch(&devices, &zones, &ha)?;
|
||||
moved += deleted;
|
||||
if deleted == 0 { break; }
|
||||
if deleted == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(moved)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user