Files
quicproquo/crates/meshservice/examples/housing_service.rs
Christian Nennemann 150f30b0d6 feat(p2p): add MeshNode integrating all production modules
New mesh_node.rs providing a production-ready node:
- MeshNodeBuilder for fluent configuration
- MeshConfig integration for all settings
- MeshMetrics tracking for all operations
- Rate limiting on incoming messages
- Backpressure controller
- Graceful shutdown via ShutdownCoordinator
- Optional FappRouter based on capabilities
- MeshRouter for envelope routing
- TransportManager for multi-transport support

Key APIs:
- MeshNodeBuilder::new().fapp_relay().build()
- node.process_incoming() with rate limiting + metrics
- node.gc() for store/routing table cleanup
- node.shutdown() for graceful termination

222 tests passing (203 lib + 3 fapp_flow + 16 multi_node)
2026-04-01 18:45:41 +02:00

98 lines
3.6 KiB
Rust

//! Housing Service Demo
//!
//! Demonstrates landlord listing and seeker query flow.
use meshservice::{
capabilities,
identity::ServiceIdentity,
router::ServiceRouter,
services::housing::{
amenities, create_announce, create_query, HousingService, ListingAnnounce, ListingQuery,
ListingType,
},
};
fn main() {
println!("=== Housing Service Demo ===\n");
// Create identities
let landlord1 = ServiceIdentity::generate();
let landlord2 = ServiceIdentity::generate();
let seeker = ServiceIdentity::generate();
// Create router with Housing service
let mut router = ServiceRouter::new(capabilities::RELAY);
router.register(Box::new(HousingService::relay()));
// Landlord 1: Kreuzberg apartment
let listing1 = ListingAnnounce::new(ListingType::Apartment, 65, 950, "104")
.with_rooms(2)
.with_amenities(amenities::FURNISHED | amenities::BALCONY | amenities::INTERNET)
.with_title("Sunny 2-room in Kreuzberg");
println!("Landlord 1 announces:");
println!(" {} sqm {} in {}xx", listing1.size_sqm, "Apartment", listing1.postal_prefix);
println!(" Rent: {} EUR/month", listing1.rent_euros());
println!(" Rooms: {}", listing1.rooms);
println!(" Amenities: Furnished, Balcony, Internet\n");
let msg1 = create_announce(&landlord1, &listing1, 1).unwrap();
router.handle(msg1, Some(landlord1.public_key())).unwrap();
// Landlord 2: Neukölln shared flat room
let listing2 = ListingAnnounce::new(ListingType::Room, 18, 450, "120")
.with_rooms(1)
.with_amenities(amenities::WASHING_MACHINE | amenities::INTERNET)
.with_title("Room in friendly WG");
println!("Landlord 2 announces:");
println!(" {} sqm {} in {}xx", listing2.size_sqm, "Room", listing2.postal_prefix);
println!(" Rent: {} EUR/month", listing2.rent_euros());
println!(" Amenities: Washing machine, Internet\n");
let msg2 = create_announce(&landlord2, &listing2, 1).unwrap();
router.handle(msg2, Some(landlord2.public_key())).unwrap();
println!("Total listings in store: {}\n", router.store().len());
// Seeker 1: Looking for affordable apartment
println!("--- Seeker Query 1: Affordable apartment ---");
let query1 = ListingQuery::new("10", 800) // Any 10xxx area, max 800 EUR
.with_type(ListingType::Apartment)
.with_min_size(40);
println!(" Area: 10xxx");
println!(" Type: Apartment");
println!(" Max rent: 800 EUR");
println!(" Min size: 40 sqm\n");
let query_msg1 = create_query(&seeker, &query1).unwrap();
let matches1 = router.query(&query_msg1);
println!("Found {} matches:", matches1.len());
for m in &matches1 {
if let Ok(l) = ListingAnnounce::from_bytes(&m.message.payload) {
println!(" - {} ({}xx, {} EUR)", l.title.as_deref().unwrap_or("No title"), l.postal_prefix, l.rent_euros());
}
}
// Seeker 2: Looking for any cheap room
println!("\n--- Seeker Query 2: Any room under 500 EUR ---");
let query2 = ListingQuery::new("1", 500); // Any 1xxxx area
let query_msg2 = create_query(&seeker, &query2).unwrap();
let matches2 = router.query(&query_msg2);
println!("Found {} matches:", matches2.len());
for m in &matches2 {
if let Ok(l) = ListingAnnounce::from_bytes(&m.message.payload) {
println!(" - {} ({}xx, {} sqm, {} EUR)",
l.title.as_deref().unwrap_or("No title"),
l.postal_prefix,
l.size_sqm,
l.rent_euros()
);
}
}
println!("\n=== Demo Complete ===");
}