add streaming body to requests and responses #3
1 changed files with 129 additions and 4 deletions
|
@ -1,17 +1,24 @@
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use log::info;
|
use async_trait::async_trait;
|
||||||
|
use bytes::Bytes;
|
||||||
|
use futures::{stream, StreamExt};
|
||||||
|
use log::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
use tokio::sync::watch;
|
||||||
|
|
||||||
use sodiumoxide::crypto::auth;
|
use sodiumoxide::crypto::auth;
|
||||||
use sodiumoxide::crypto::sign::ed25519;
|
use sodiumoxide::crypto::sign::ed25519;
|
||||||
|
|
||||||
|
use netapp::endpoint::*;
|
||||||
|
use netapp::message::*;
|
||||||
use netapp::peering::fullmesh::*;
|
use netapp::peering::fullmesh::*;
|
||||||
use netapp::util::*;
|
use netapp::util::*;
|
||||||
|
use netapp::{NetApp, NodeID};
|
||||||
use netapp::NetApp;
|
|
||||||
|
|
||||||
#[derive(StructOpt, Debug)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(name = "netapp")]
|
#[structopt(name = "netapp")]
|
||||||
|
@ -92,8 +99,126 @@ async fn main() {
|
||||||
|
|
||||||
let watch_cancel = netapp::util::watch_ctrl_c();
|
let watch_cancel = netapp::util::watch_ctrl_c();
|
||||||
|
|
||||||
|
let example = Arc::new(Example {
|
||||||
|
netapp: netapp.clone(),
|
||||||
|
fullmesh: peering.clone(),
|
||||||
|
example_endpoint: netapp.endpoint("__netapp/examples/fullmesh.rs/Example".into()),
|
||||||
|
});
|
||||||
|
example.example_endpoint.set_handler(example.clone());
|
||||||
|
|
||||||
tokio::join!(
|
tokio::join!(
|
||||||
|
example.exchange_loop(watch_cancel.clone()),
|
||||||
netapp.listen(listen_addr, public_addr, watch_cancel.clone()),
|
netapp.listen(listen_addr, public_addr, watch_cancel.clone()),
|
||||||
peering.run(watch_cancel),
|
peering.run(watch_cancel),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----
|
||||||
|
|
||||||
|
struct Example {
|
||||||
|
netapp: Arc<NetApp>,
|
||||||
|
fullmesh: Arc<FullMeshPeeringStrategy>,
|
||||||
|
example_endpoint: Arc<Endpoint<ExampleMessage, Self>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Example {
|
||||||
|
async fn exchange_loop(self: Arc<Self>, must_exit: watch::Receiver<bool>) {
|
||||||
|
let mut i = 12000;
|
||||||
|
while !*must_exit.borrow() {
|
||||||
|
tokio::time::sleep(Duration::from_secs(7)).await;
|
||||||
|
|
||||||
|
let peers = self.fullmesh.get_peer_list();
|
||||||
|
for p in peers.iter() {
|
||||||
|
let id = p.id;
|
||||||
|
if id == self.netapp.id {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
let example_field = i;
|
||||||
|
let self2 = self.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
info!(
|
||||||
|
"Send example query {} to {}",
|
||||||
|
example_field,
|
||||||
|
hex::encode(id)
|
||||||
|
);
|
||||||
|
let stream =
|
||||||
|
Box::pin(stream::iter([100, 200, 300, 400]).then(|x| async move {
|
||||||
|
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||||
|
Ok(Bytes::from(vec![(x % 256) as u8; 133 * x]))
|
||||||
|
}));
|
||||||
|
match self2
|
||||||
|
.example_endpoint
|
||||||
|
.call_streaming(
|
||||||
|
&id,
|
||||||
|
Req::new(ExampleMessage { example_field })
|
||||||
|
.unwrap()
|
||||||
|
.with_stream(stream),
|
||||||
|
PRIO_NORMAL,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(resp) => {
|
||||||
|
let (resp, stream) = resp.into_parts();
|
||||||
|
info!(
|
||||||
|
"Got example response to {} from {}: {:?}",
|
||||||
|
example_field,
|
||||||
|
hex::encode(id),
|
||||||
|
resp
|
||||||
|
);
|
||||||
|
let mut stream = stream.unwrap();
|
||||||
|
while let Some(x) = stream.next().await {
|
||||||
|
info!("Response: stream got bytes {:?}", x.map(|b| b.len()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => warn!("Error with example request: {}", e),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl StreamingEndpointHandler<ExampleMessage> for Example {
|
||||||
|
async fn handle(
|
||||||
|
self: &Arc<Self>,
|
||||||
|
mut msg: Req<ExampleMessage>,
|
||||||
|
_from: NodeID,
|
||||||
|
) -> Resp<ExampleMessage> {
|
||||||
|
info!(
|
||||||
|
"Got example message: {:?}, sending example response",
|
||||||
|
msg.msg()
|
||||||
|
);
|
||||||
|
let source_stream = msg.take_stream().unwrap();
|
||||||
|
let new_stream = Box::pin(source_stream.then(|x| async move {
|
||||||
|
info!(
|
||||||
|
"Handler: stream got bytes {:?}",
|
||||||
|
x.as_ref().map(|b| b.len())
|
||||||
|
);
|
||||||
|
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||||
|
Ok(Bytes::from(vec![
|
||||||
|
10u8;
|
||||||
|
x.map(|b| b.len()).unwrap_or(1422) * 2
|
||||||
|
]))
|
||||||
|
}));
|
||||||
|
Resp::new(ExampleResponse {
|
||||||
|
example_field: false,
|
||||||
|
})
|
||||||
|
.with_stream(new_stream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
struct ExampleMessage {
|
||||||
|
example_field: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
struct ExampleResponse {
|
||||||
|
example_field: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Message for ExampleMessage {
|
||||||
|
type Response = ExampleResponse;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue