blob: ccd0e7fea9948203a90cbc09a121d08e77e8dabc [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// [START part_1_add_connection_count]
use {
// [START_EXCLUDE]
fidl_fuchsia_examples_inspect::{ReverserRequest, ReverserRequestStream},
fuchsia_async as fasync,
fuchsia_inspect as inspect,
// [END_EXCLUDE]
fuchsia_inspect::NumericProperty,
// [START_EXCLUDE]
futures::TryStreamExt,
std::sync::Arc,
// [END_EXCLUDE]
};
pub struct ReverserServerFactory {
node: inspect::Node,
// [START_EXCLUDE]
request_count: Arc<inspect::UintProperty>,
// [END_EXCLUDE]
connection_count: inspect::UintProperty,
}
impl ReverserServerFactory {
pub fn new(node: inspect::Node) -> Self {
// [START_EXCLUDE]
let request_count = Arc::new(node.create_uint("total_requests", 0));
// [END_EXCLUDE]
let connection_count = node.create_uint("connection_count", 0);
Self {
node,
// [START_EXCLUDE]
request_count,
// [END_EXCLUDE]
connection_count,
}
}
pub fn spawn_new(&self, stream: ReverserRequestStream) {
self.connection_count.add(1);
// [END part_1_add_connection_count]
let node = self.node.create_child(inspect::unique_name("connection"));
let metrics = ReverserServerMetrics::new(node, self.request_count.clone());
ReverserServer::new(metrics).spawn(stream);
}
}
// The default implementation of ReverserServerMetrics is a no-op on the inspect properties. We use
// it for testing in this codelab. Future parts of the codelab will actually test our inspect
// writing.
#[derive(Default)]
struct ReverserServerMetrics {
global_request_count: Arc<inspect::UintProperty>,
request_count: inspect::UintProperty,
response_count: inspect::UintProperty,
_node: inspect::Node,
}
impl ReverserServerMetrics {
fn new(node: inspect::Node, global_request_count: Arc<inspect::UintProperty>) -> Self {
let request_count = node.create_uint("request_count", 0);
let response_count = node.create_uint("response_count", 0);
let metrics = Self {
global_request_count,
// Hold to the node until we are done with this connection.
_node: node,
request_count,
response_count,
};
metrics
}
}
struct ReverserServer {
metrics: ReverserServerMetrics,
}
impl ReverserServer {
fn new(metrics: ReverserServerMetrics) -> Self {
Self { metrics }
}
pub fn spawn(self, mut stream: ReverserRequestStream) {
fasync::Task::local(async move {
let _ = &self;
while let Some(request) = stream.try_next().await.expect("serve reverser") {
self.metrics.request_count.add(1);
self.metrics.global_request_count.add(1);
let ReverserRequest::Reverse { input, responder } = request;
let result = input.chars().rev().collect::<String>();
responder.send(&result).expect("send reverse request response");
self.metrics.response_count.add(1);
}
})
.detach();
}
}
#[cfg(test)]
mod tests {
use {
super::*,
anyhow::Error,
fidl_fuchsia_examples_inspect::{ReverserMarker, ReverserProxy},
// CODELAB: Include the inspect test module.
};
#[fuchsia::test]
async fn test_reverser() -> Result<(), Error> {
let reverser = open_reverser()?;
let result = reverser.reverse("hello").await?;
assert_eq!(result, "olleh");
// CODELAB: assert that the inspect data is correct.
Ok(())
}
fn open_reverser() -> Result<ReverserProxy, Error> {
let (proxy, stream) = fidl::endpoints::create_proxy_and_stream::<ReverserMarker>()?;
let reverser = ReverserServer::new(ReverserServerMetrics::default());
reverser.spawn(stream);
Ok(proxy)
}
}