settings/agent/
restore_agent.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::agent::{AgentError, Context, Invocation, InvocationResult, Lifespan, Payload};
6use crate::base::SettingType;
7use crate::event::{restore, Event, Publisher};
8use crate::handler::base::{Error, Payload as HandlerPayload, Request};
9use crate::message::base::Audience;
10use crate::service;
11use fuchsia_async as fasync;
12use std::collections::HashSet;
13
14/// The Restore Agent is responsible for signaling to all components to restore
15/// external sources to the last known value. It is invoked during startup.
16#[derive(Debug)]
17pub(crate) struct RestoreAgent {
18    messenger: service::message::Messenger,
19    event_publisher: Publisher,
20    available_components: HashSet<SettingType>,
21}
22
23impl RestoreAgent {
24    pub(crate) async fn create(context: Context) {
25        let mut agent = RestoreAgent {
26            messenger: context.create_messenger().await.expect("should acquire messenger"),
27            event_publisher: context.get_publisher(),
28            available_components: context.available_components,
29        };
30
31        let mut receptor = context.receptor;
32        fasync::Task::local(async move {
33            while let Ok((Payload::Invocation(invocation), client)) =
34                receptor.next_of::<Payload>().await
35            {
36                let _ = client.reply(Payload::Complete(agent.handle(invocation).await).into());
37            }
38        })
39        .detach();
40    }
41
42    async fn handle(&mut self, invocation: Invocation) -> InvocationResult {
43        match invocation.lifespan {
44            Lifespan::Initialization => {
45                for component in &self.available_components {
46                    let mut receptor = self.messenger.message(
47                        HandlerPayload::Request(Request::Restore).into(),
48                        Audience::Address(service::Address::Handler(*component)),
49                    );
50
51                    let response = receptor
52                        .next_of::<HandlerPayload>()
53                        .await
54                        .map_err(|e| {
55                            log::error!("Received error when getting payload: {:?}", e);
56                            AgentError::UnexpectedError
57                        })?
58                        .0;
59                    if let HandlerPayload::Response(response) = response {
60                        match response {
61                            Ok(_) => {
62                                continue;
63                            }
64                            Err(Error::UnimplementedRequest(setting_type, _)) => {
65                                self.event_publisher
66                                    .send_event(Event::Restore(restore::Event::NoOp(setting_type)));
67                                continue;
68                            }
69                            Err(Error::UnhandledType(setting_type)) => {
70                                log::info!("setting not available for restore: {:?}", setting_type);
71                                continue;
72                            }
73                            e => {
74                                log::error!("error during restore for {component:?}: {e:?}");
75                                return Err(AgentError::UnexpectedError);
76                            }
77                        }
78                    } else {
79                        log::error!("Error because of response: {:?}", response);
80                        return Err(AgentError::UnexpectedError);
81                    }
82                }
83            }
84            _ => {
85                return Err(AgentError::UnhandledLifespan);
86            }
87        }
88
89        Ok(())
90    }
91}