fn handle_event(&mut self, ev: Event) -> Vec<Event> {
        match ev {
            Event::ServiceExited(service_name, exit_code) => {
                let pid = self.repo.get_sh(&service_name).pid.unwrap();
                self.repo.remove_pid(pid);
                let service_handler = self.repo.get_mut_sh(&service_name);
                service_handler.shutting_down_start = None;
                service_handler.pid = None;

                let has_failed = !service_handler
                    .service()
                    .failure
                    .successful_exit_code
                    .contains(&exit_code);

                // If it has failed too quickly, increase service_handler's restart attempts
                // and check if it has more attempts left.
                if service_handler.has_some_failed_healthchecks()
                    && service_handler.is_early_state()
                {
                    service_handler.restart_attempts += 1;
                }

                let new_status = if has_failed
                    || (service_handler.status == ServiceStatus::Running
                        && service_handler.has_some_failed_healthchecks())
                {
                    warn!(
                        "Service: {} has failed, exit code: {}, healthchecks: {} ({:?})",
                        service_handler.name(),
                        exit_code,
                        service_handler.has_some_failed_healthchecks(),
                        service_handler.healthiness_checks_failed
                    );
                    ServiceStatus::Failed
                } else {
                    info!(
                        "Service: {} successfully exited with: {}.",
                        service_handler.name(),
                        exit_code
                    );
                    ServiceStatus::Success
                };
                let (new_sh, new_status) = service_handler.change_status(new_status);
                self.repo.insert_sh_by_name(service_name.clone(), new_sh);
                debug!(
                    "{}: new status for exited service: {:?}",
                    service_name, new_status
                );
                vec![Event::StatusChanged(service_name, new_status)]
            }
            Event::Run(service_name) if self.repo.get_sh(&service_name).is_initial() => {
                let service_handler = self.repo.get_mut_sh(&service_name);
                service_handler.status = ServiceStatus::Starting;
                let evs = vec![Event::StatusChanged(service_name, ServiceStatus::Starting)];

                let res = healthcheck::prepare_service(&service_handler.service().healthiness);
                if res.is_err() {
                    //TODO: maybe this is a bit too aggressive.
                    error!(
                        "Prepare healthiness checks failed for service: {}, shutting down...",
                        service_handler.name()
                    );
                    service_handler.status = ServiceStatus::FinishedFailed;
                    self.status = LifecycleStatus::ShuttingDown(ShuttingDown::Gracefuly);
                    return vec![
                        Event::StatusUpdate(
                            service_handler.name().clone(),
                            ServiceStatus::FinishedFailed,
                        ),
                        Event::ShuttingDownInitiated(ShuttingDown::Gracefuly),
                    ];
                }
                let backoff = service_handler
                    .service()
                    .restart
                    .backoff
                    .mul(service_handler.restart_attempts);
                process_spawner::spawn_fork_exec_handler(
                    service_handler.service().clone(),
                    backoff,
                    self.repo.bus.join_bus(),
                );
                evs
            }
            Event::SpawnFailed(s_name) => {
                let service_handler = self.repo.get_mut_sh(&s_name);
                service_handler.status = ServiceStatus::Failed;
                vec![Event::StatusUpdate(s_name, ServiceStatus::Failed)]
            }
            Event::Kill(service_name) => {
                debug!("Received kill request");
                let service_handler = self.repo.get_mut_sh(&service_name);
                if service_handler.is_in_killing() {
                    service_handler.shutting_down_started();
                    kill(service_handler, None);
                } else {
                    debug!(
                        "Cannot send kill request, service was in: {}",
                        service_handler.status
                    );
                }
                vec![]
            }
            Event::ForceKill(service_name) if self.repo.get_sh(&service_name).is_in_killing() => {
                debug!("Going to forcekill {}", service_name);
                let service_handler = self.repo.get_mut_sh(&service_name);
                kill(service_handler, Some(signal::SIGKILL));
                service_handler.status = ServiceStatus::Failed;
                vec![Event::new_status_changed(
                    service_handler.name(),
                    ServiceStatus::Failed,
                )]
            }
            Event::PidChanged(service_name, pid) => {
                self.repo.add_pid(pid, service_name.clone());

                let service_handler = self.repo.get_mut_sh(&service_name);
                service_handler.pid = Some(pid);
                if service_handler.is_in_killing() {
                    // Ah! Gotcha!
                    service_handler.shutting_down_start = Some(Instant::now());
                    kill(service_handler, None)
                } else {
                    service_handler.status = ServiceStatus::Started;
                    return vec![Event::StatusChanged(service_name, ServiceStatus::Started)];
                }

                vec![]
            }
            Event::HealthCheck(s_name, health) => {
                let sh = self.repo.get_mut_sh(&s_name);
                // Count the failed healthiness checks. The state change producer wll handle states
                // changes (if they're needed)
                sh.add_healthcheck_event(health);
                vec![]
            }
            Event::ShuttingDownInitiated(shutting_down) => {
                match shutting_down {
                    ShuttingDown::Gracefuly => {
                        warn!("Gracefully stopping...");
                    }
                    ShuttingDown::Forcefuly => {
                        warn!("Terminating all services...");
                    }
                }
                self.status = LifecycleStatus::ShuttingDown(shutting_down);
                signal_handling::clear_sigtem();
                vec![]
            }
            Event::StatusUpdate(service_name, new_status) => {
                let service_handler = self.repo.get_sh(&service_name);

                let (new_sh, new_status) = service_handler.change_status(new_status);
                if new_status != service_handler.status {
                    self.repo.insert_sh_by_name(service_name.clone(), new_sh);
                    // this is the only place where the new_status changed is emitted.
                    vec![Event::new_status_changed(&service_name, new_status)]
                } else {
                    debug!(
                        "Status Update event handler, new status {} == {} old status",
                        new_status, service_handler.status
                    );
                    vec![]
                }
            }
            ev => {
                trace!("ignoring: {:?}", ev);
                vec![]
            }
        }
    }
/// Handle the events, returns Events (state changes) to be dispatched.
Handle the events, returns Events (state changes) to be dispatched.
Handle the events returns Events ( state changes ) to be dispatched .
fn handle_event(&mut self, ev: Event) -> Vec<Event> {
        match ev {
            Event::ServiceExited(service_name, exit_code) => {
                let pid = self.repo.get_sh(&service_name).pid.unwrap();
                self.repo.remove_pid(pid);
                let service_handler = self.repo.get_mut_sh(&service_name);
                service_handler.shutting_down_start = None;
                service_handler.pid = None;
                let has_failed = !service_handler
                    .service()
                    .failure
                    .successful_exit_code
                    .contains(&exit_code);
                // If it has failed too quickly, increase service_handler's restart attempts
                // and check if it has more attempts left.
                if service_handler.has_some_failed_healthchecks()
                    && service_handler.is_early_state()
                {
                    service_handler.restart_attempts += 1;
                }
                let new_status = if has_failed
                    || (service_handler.status == ServiceStatus::Running
                        && service_handler.has_some_failed_healthchecks())
                {
                    warn!(
                        "Service: {} has failed, exit code: {}, healthchecks: {} ({:?})",
                        service_handler.name(),
                        exit_code,
                        service_handler.has_some_failed_healthchecks(),
                        service_handler.healthiness_checks_failed
                    );
                    ServiceStatus::Failed
                } else {
                    info!(
                        "Service: {} successfully exited with: {}.",
                        service_handler.name(),
                        exit_code
                    );
                    ServiceStatus::Success
                };
                let (new_sh, new_status) = service_handler.change_status(new_status);
                self.repo.insert_sh_by_name(service_name.clone(), new_sh);
                debug!(
                    "{}: new status for exited service: {:?}",
                    service_name, new_status
                );
                vec![Event::StatusChanged(service_name, new_status)]
            }
            Event::Run(service_name) if self.repo.get_sh(&service_name).is_initial() => {
                let service_handler = self.repo.get_mut_sh(&service_name);
                service_handler.status = ServiceStatus::Starting;
                let evs = vec![Event::StatusChanged(service_name, ServiceStatus::Starting)];
                let res = healthcheck::prepare_service(&service_handler.service().healthiness);
                if res.is_err() {
                    //TODO: maybe this is a bit too aggressive.
                    error!(
                        "Prepare healthiness checks failed for service: {}, shutting down...",
                        service_handler.name()
                    );
                    service_handler.status = ServiceStatus::FinishedFailed;
                    self.status = LifecycleStatus::ShuttingDown(ShuttingDown::Gracefuly);
                    return vec![
                        Event::StatusUpdate(
                            service_handler.name().clone(),
                            ServiceStatus::FinishedFailed,
                        ),
                        Event::ShuttingDownInitiated(ShuttingDown::Gracefuly),
                    ];
                }
                let backoff = service_handler
                    .service()
                    .restart
                    .backoff
                    .mul(service_handler.restart_attempts);
                process_spawner::spawn_fork_exec_handler(
                    service_handler.service().clone(),
                    backoff,
                    self.repo.bus.join_bus(),
                );
                evs
            }
            Event::SpawnFailed(s_name) => {
                let service_handler = self.repo.get_mut_sh(&s_name);
                service_handler.status = ServiceStatus::Failed;
                vec![Event::StatusUpdate(s_name, ServiceStatus::Failed)]
            }
            Event::Kill(service_name) => {
                debug!("Received kill request");
                let service_handler = self.repo.get_mut_sh(&service_name);
                if service_handler.is_in_killing() {
                    service_handler.shutting_down_started();
                    kill(service_handler, None);
                } else {
                    debug!(
                        "Cannot send kill request, service was in: {}",
                        service_handler.status
                    );
                }
                vec![]
            }
            Event::ForceKill(service_name) if self.repo.get_sh(&service_name).is_in_killing() => {
                debug!("Going to forcekill {}", service_name);
                let service_handler = self.repo.get_mut_sh(&service_name);
                kill(service_handler, Some(signal::SIGKILL));
                service_handler.status = ServiceStatus::Failed;
                vec![Event::new_status_changed(
                    service_handler.name(),
                    ServiceStatus::Failed,
                )]
            }
            Event::PidChanged(service_name, pid) => {
                self.repo.add_pid(pid, service_name.clone());
                let service_handler = self.repo.get_mut_sh(&service_name);
                service_handler.pid = Some(pid);
                if service_handler.is_in_killing() {
                    // Ah! Gotcha!
                    service_handler.shutting_down_start = Some(Instant::now());
                    kill(service_handler, None)
                } else {
                    service_handler.status = ServiceStatus::Started;
                    return vec![Event::StatusChanged(service_name, ServiceStatus::Started)];
                }
                vec![]
            }
            Event::HealthCheck(s_name, health) => {
                let sh = self.repo.get_mut_sh(&s_name);
                // Count the failed healthiness checks. The state change producer wll handle states
                // changes (if they're needed)
                sh.add_healthcheck_event(health);
                vec![]
            }
            Event::ShuttingDownInitiated(shutting_down) => {
                match shutting_down {
                    ShuttingDown::Gracefuly => {
                        warn!("Gracefully stopping...");
                    }
                    ShuttingDown::Forcefuly => {
                        warn!("Terminating all services...");
                    }
                }
                self.status = LifecycleStatus::ShuttingDown(shutting_down);
                signal_handling::clear_sigtem();
                vec![]
            }
            Event::StatusUpdate(service_name, new_status) => {
                let service_handler = self.repo.get_sh(&service_name);
                let (new_sh, new_status) = service_handler.change_status(new_status);
                if new_status != service_handler.status {
                    self.repo.insert_sh_by_name(service_name.clone(), new_sh);
                    // this is the only place where the new_status changed is emitted.
                    vec![Event::new_status_changed(&service_name, new_status)]
                } else {
                    debug!(
                        "Status Update event handler, new status {} == {} old status",
                        new_status, service_handler.status
                    );
                    vec![]
                }
            }
            ev => {
                trace!("ignoring: {:?}", ev);
                vec![]
            }
        }
    }
fn handle_event ( & mut self , ev : Event ) -> Vec < Event > { match ev { Event :: ServiceExited ( service_name , exit_code ) => { let pid = self . repo . get_sh ( & service_name ) . pid . unwrap ( ) ; self . repo . remove_pid ( pid ) ; let service_handler = self . repo . get_mut_sh ( & service_name ) ; service_handler . shutting_down_start = None ; service_handler . pid = None ; let has_failed = ! service_handler . service ( ) . failure . successful_exit_code . contains ( & exit_code ) ; // If it has failed too quickly, increase service_handler's restart attempts // and check if it has more attempts left. if service_handler . has_some_failed_healthchecks ( ) && service_handler . is_early_state ( ) { service_handler . restart_attempts += 1 ; } let new_status = if has_failed || ( service_handler . status == ServiceStatus :: Running && service_handler . has_some_failed_healthchecks ( ) ) { warn ! ( " " service_handler name ( ) exit_code service_handler has_some_failed_healthchecks ( ) service_handler healthiness_checks_failed ) ; ServiceStatus :: Failed } else { info ! ( " " service_handler name ( ) exit_code ) ; ServiceStatus :: Success } ; let ( new_sh , new_status ) = service_handler . change_status ( new_status ) ; self . repo . insert_sh_by_name ( service_name . clone ( ) , new_sh ) ; debug ! ( " " service_name new_status ) ; vec ! [ Event StatusChanged ( service_name new_status ) ] } Event :: Run ( service_name ) if self . repo . get_sh ( & service_name ) . is_initial ( ) => { let service_handler = self . repo . get_mut_sh ( & service_name ) ; service_handler . status = ServiceStatus :: Starting ; let evs = vec ! [ Event StatusChanged ( service_name ServiceStatus Starting ) ] ; let res = healthcheck :: prepare_service ( & service_handler . service ( ) . healthiness ) ; if res . is_err ( ) { //TODO: maybe this is a bit too aggressive. error ! ( " " service_handler name ( ) ) ; service_handler . status = ServiceStatus :: FinishedFailed ; self . status = LifecycleStatus :: ShuttingDown ( ShuttingDown :: Gracefuly ) ; return vec ! [ Event StatusUpdate ( service_handler name ( ) clone ( ) ServiceStatus FinishedFailed ) Event ShuttingDownInitiated ( ShuttingDown Gracefuly ) ] ; } let backoff = service_handler . service ( ) . restart . backoff . mul ( service_handler . restart_attempts ) ; process_spawner :: spawn_fork_exec_handler ( service_handler . service ( ) . clone ( ) , backoff , self . repo . bus . join_bus ( ) , ) ; evs } Event :: SpawnFailed ( s_name ) => { let service_handler = self . repo . get_mut_sh ( & s_name ) ; service_handler . status = ServiceStatus :: Failed ; vec ! [ Event StatusUpdate ( s_name ServiceStatus Failed ) ] } Event :: Kill ( service_name ) => { debug ! ( " " ) ; let service_handler = self . repo . get_mut_sh ( & service_name ) ; if service_handler . is_in_killing ( ) { service_handler . shutting_down_started ( ) ; kill ( service_handler , None ) ; } else { debug ! ( " " service_handler status ) ; } vec ! [ ] } Event :: ForceKill ( service_name ) if self . repo . get_sh ( & service_name ) . is_in_killing ( ) => { debug ! ( " " service_name ) ; let service_handler = self . repo . get_mut_sh ( & service_name ) ; kill ( service_handler , Some ( signal :: SIGKILL ) ) ; service_handler . status = ServiceStatus :: Failed ; vec ! [ Event new_status_changed ( service_handler name ( ) ServiceStatus Failed ) ] } Event :: PidChanged ( service_name , pid ) => { self . repo . add_pid ( pid , service_name . clone ( ) ) ; let service_handler = self . repo . get_mut_sh ( & service_name ) ; service_handler . pid = Some ( pid ) ; if service_handler . is_in_killing ( ) { // Ah! Gotcha! service_handler . shutting_down_start = Some ( Instant :: now ( ) ) ; kill ( service_handler , None ) } else { service_handler . status = ServiceStatus :: Started ; return vec ! [ Event StatusChanged ( service_name ServiceStatus Started ) ] ; } vec ! [ ] } Event :: HealthCheck ( s_name , health ) => { let sh = self . repo . get_mut_sh ( & s_name ) ; // Count the failed healthiness checks. The state change producer wll handle states // changes (if they're needed) sh . add_healthcheck_event ( health ) ; vec ! [ ] } Event :: ShuttingDownInitiated ( shutting_down ) => { match shutting_down { ShuttingDown :: Gracefuly => { warn ! ( " " ) ; } ShuttingDown :: Forcefuly => { warn ! ( " " ) ; } } self . status = LifecycleStatus :: ShuttingDown ( shutting_down ) ; signal_handling :: clear_sigtem ( ) ; vec ! [ ] } Event :: StatusUpdate ( service_name , new_status ) => { let service_handler = self . repo . get_sh ( & service_name ) ; let ( new_sh , new_status ) = service_handler . change_status ( new_status ) ; if new_status != service_handler . status { self . repo . insert_sh_by_name ( service_name . clone ( ) , new_sh ) ; // this is the only place where the new_status changed is emitted. vec ! [ Event new_status_changed ( service_name new_status ) ] } else { debug ! ( " " new_status service_handler status ) ; vec ! [ ] } } ev => { trace ! ( " " ev ) ; vec ! [ ] } } }
Handle the events, returns Events (state changes) to be dispatched.
Handle the events returns Events ( state changes ) to be dispatched .
&mut self
ev
Event
&mut self
ev
Event