hydro_test/cluster/
chat.rs

1use std::hash::{DefaultHasher, Hash, Hasher};
2
3use colored::{Color, Colorize};
4use hydro_lang::*;
5use palette::{FromColor, Hsv, Srgb};
6
7pub struct Server {}
8
9pub struct Clients {}
10
11use serde::{Deserialize, Serialize};
12
13#[derive(Serialize, Deserialize, Clone)]
14pub struct ChatMsg {
15    pub content: String,
16}
17
18// To enable colored output in the terminal, set the environment variable
19// `CLICOLOR_FORCE=1`. By default, the `colored` crate only applies color
20// when the output is a terminal, to avoid issues with terminals that do
21// not support color.
22pub fn chat_server<'a>(flow: &FlowBuilder<'a>) -> (Process<'a, Server>, Cluster<'a, Clients>) {
23    // For testing, use a fixed cluster of clients. In future we should support unbounded clients.
24    // This is a workaround for the fact that we don't have a way to create a cluster of
25    // unbounded clients in the current version of hydro.
26
27    let clients = flow.cluster::<Clients>();
28    // Assume single server.
29    let server = flow.process::<Server>();
30
31    // 1 chat message is generated from each client
32    let client_requests = clients
33        .source_iter(q!([ChatMsg {
34            content: format!("Hi, it's me! Client #{}!", CLUSTER_SELF_ID.raw_id)
35        }]))
36        .send_bincode(&server)
37        .clone()
38        .inspect(q!(|(id, msg)| println!(
39            "...forwarding chat {} from client #{}...",
40            msg.content, id
41        )));
42    client_requests
43        .broadcast_bincode(&clients)
44        .map(q!(|(id, msg)| (
45            id,
46            msg.content.color(self::hash_to_color(id.raw_id + 10))
47        )))
48        .for_each(q!(|(id, m)| println!("From {}: {:}", id.raw_id, m)));
49
50    (server, clients)
51}
52
53fn hash_to_color<T: Hash>(input: T) -> Color {
54    let mut hasher = DefaultHasher::new();
55    input.hash(&mut hasher);
56    let hash = hasher.finish();
57
58    // Map hash to a hue between 0–360
59    let hue = (hash % 360) as f32;
60    let hsv = Hsv::new(hue, 1.0, 1.0);
61    let rgb: Srgb<u8> = Srgb::from_color(hsv).into_format();
62
63    Color::TrueColor {
64        r: rgb.red,
65        g: rgb.green,
66        b: rgb.blue,
67    }
68}