Browse Source

Only publish programs which have changed

master
Alex Mikhalev 4 years ago
parent
commit
5f54aa037b
  1. 32
      sprinklers_mqtt/src/lib.rs
  2. 32
      sprinklers_mqtt/src/update_listener.rs

32
sprinklers_mqtt/src/lib.rs

@ -103,21 +103,47 @@ impl MqttInterface {
pub async fn publish_programs(&mut self, programs: &Programs) -> eyre::Result<()> { pub async fn publish_programs(&mut self, programs: &Programs) -> eyre::Result<()> {
let program_ids: Vec<_> = programs.keys().cloned().collect(); let program_ids: Vec<_> = programs.keys().cloned().collect();
self.publish_data(self.topics.programs(), &program_ids) self.publish_program_ids(&program_ids).await?;
.await
.wrap_err("failed to publish program ids")?;
for program in programs.values() { for program in programs.values() {
self.publish_program(program).await?; self.publish_program(program).await?;
} }
Ok(()) Ok(())
} }
pub async fn publish_program_ids(&mut self, program_ids: &[ProgramId]) -> eyre::Result<()> {
self.publish_data(self.topics.programs(), &program_ids)
.await
.wrap_err("failed to publish program ids")?;
Ok(())
}
pub async fn publish_program(&mut self, program: &Program) -> eyre::Result<()> { pub async fn publish_program(&mut self, program: &Program) -> eyre::Result<()> {
self.publish_data(self.topics.program_data(program.id), &program) self.publish_data(self.topics.program_data(program.id), &program)
.await .await
.wrap_err("failed to publish program") .wrap_err("failed to publish program")
} }
pub async fn publish_programs_diff(
&mut self,
old_programs: &Programs,
programs: &Programs,
) -> eyre::Result<()> {
for (id, program) in programs {
let publish = match old_programs.get(id) {
Some(old_program) => !Arc::ptr_eq(old_program, program),
None => {
let program_ids: Vec<_> = programs.keys().cloned().collect();
self.publish_program_ids(&program_ids).await?;
true
}
};
if publish {
self.publish_program(program).await?;
}
}
Ok(())
}
pub async fn publish_program_running( pub async fn publish_program_running(
&mut self, &mut self,
program_id: ProgramId, program_id: ProgramId,

32
sprinklers_mqtt/src/update_listener.rs

@ -5,20 +5,22 @@ use sprinklers_actors::{
}; };
use actix::{fut::wrap_future, Actor, ActorContext, Addr, AsyncContext, Handler, StreamHandler}; use actix::{fut::wrap_future, Actor, ActorContext, Addr, AsyncContext, Handler, StreamHandler};
use futures_util::TryFutureExt;
use sprinklers_core::model::Programs; use sprinklers_core::model::Programs;
use std::sync::Arc;
use tokio::sync::{broadcast, watch}; use tokio::sync::{broadcast, watch};
use tracing::{trace, warn}; use tracing::{trace, warn};
struct UpdateListenerActor { struct UpdateListenerActor {
mqtt_interface: MqttInterface, mqtt_interface: MqttInterface,
has_published_program_states: bool, old_programs: Option<Programs>,
} }
impl UpdateListenerActor { impl UpdateListenerActor {
fn new(mqtt_interface: MqttInterface) -> Self { fn new(mqtt_interface: MqttInterface) -> Self {
Self { Self {
mqtt_interface, mqtt_interface,
has_published_program_states: false, old_programs: None,
} }
} }
} }
@ -116,27 +118,31 @@ impl StreamHandler<Programs> for UpdateListenerActor {
fn handle(&mut self, programs: Programs, ctx: &mut Self::Context) { fn handle(&mut self, programs: Programs, ctx: &mut Self::Context) {
let mut mqtt_interface = self.mqtt_interface.clone(); let mut mqtt_interface = self.mqtt_interface.clone();
let has_published_program_states = self.has_published_program_states; let old_programs = self.old_programs.replace(programs.clone());
self.has_published_program_states = true;
let fut = async move { let fut = async move {
if let Err(err) = mqtt_interface.publish_programs(&programs).await { match old_programs {
warn!("could not publish programs: {:?}", err); None => {
} mqtt_interface.publish_programs(&programs).await?;
// Some what of a hack // Some what of a hack
// Initialize program running states to false the first time we // Initialize program running states to false the first time we
// receive programs // receive programs
if !has_published_program_states {
for program_id in programs.keys() { for program_id in programs.keys() {
if let Err(err) = mqtt_interface mqtt_interface
.publish_program_running(*program_id, false) .publish_program_running(*program_id, false)
.await .await?;
{
warn!("could not publish program running: {:?}", err);
} }
} }
Some(old_programs) => {
mqtt_interface
.publish_programs_diff(&old_programs, &programs)
.await?;
} }
}; }
Ok(())
}
.unwrap_or_else(|err: eyre::Report| warn!("could not publish programs: {:?}", err));
ctx.spawn(wrap_future(fut)); ctx.spawn(wrap_future(fut));
} }
} }

Loading…
Cancel
Save