use async_trait::async_trait;
use mocra::prelude::*;
use serde::Serialize;
#[derive(Debug, Serialize)]
struct Page {
url: String,
status: u16,
}
struct Httpbin;
#[async_trait]
impl Spider for Httpbin {
type Item = Page;
fn name(&self) -> &str {
"httpbin"
}
async fn start(&self, s: &mut Seeds) {
s.get("https://httpbin.org/get");
}
async fn parse(&self, res: Response, cx: &mut Ctx<Self::Item>) -> Result<()> {
cx.emit(Page {
url: res.module_id(),
status: res.status_code,
});
Ok(())
}
}
#[tokio::main]
async fn main() -> Result<()> {
let args: Vec<String> = std::env::args().collect();
let cluster = if args.len() >= 3 {
let node_id: u64 = args[1].parse().unwrap_or(1);
let http_addr = args[2].clone();
let data_dir = format!("./mocra-data/node-{node_id}");
match args.get(3) {
Some(seed) => ClusterConfig::join(node_id, http_addr, data_dir, seed.clone()),
None => ClusterConfig::bootstrap(node_id, http_addr, data_dir),
}
} else {
ClusterConfig::from_env().map_err(|e| Error::new(ErrorKind::Service, Some(e)))?
};
println!(
"starting mocra cluster node {} @ {} ({})",
cluster.node_id,
cluster.http_addr,
if cluster.seeds.is_empty() {
"bootstrap"
} else {
"join"
}
);
Mocra::builder()
.spider(
Httpbin,
on_item(|p: Page| async move {
println!("[item] {} -> {}", p.url, p.status);
}),
)
.cluster(cluster)
.run()
.await
}