don't use internal state in the node

This commit is contained in:
Joe Ardent 2024-06-04 14:30:28 -07:00
parent 7a0147f88e
commit 23b95677bf

View file

@ -1,12 +1,13 @@
use nebkor_maelstrom::{kv::Kv, mk_payload, Body, Message, Node, Runner}; use nebkor_maelstrom::{kv::Kv, mk_payload, Body, Message, Node, Runner};
use serde_json::Value;
const KEY: &str = "COUNTER"; const KEY: &str = "COUNTER";
#[derive(Clone, Default)] #[derive(Clone, Default)]
struct Counter(i64); struct Counter;
fn main() { fn main() {
let node = Counter(0); let node = Counter;
let runner = Runner::new(node); let runner = Runner::new(node);
@ -20,14 +21,6 @@ fn main() {
runner.run(Some(on_init)); runner.run(Some(on_init));
} }
fn gossip(neighbors: &[&String], runner: &Runner, val: i64) {
let payload = mk_payload(&[("goss", val.into())]);
let body = Body::from_type("gossip").with_payload(payload);
for node in neighbors {
runner.send(node, body.clone());
}
}
impl Node for Counter { impl Node for Counter {
fn handle(&mut self, runner: &Runner, req: Message) { fn handle(&mut self, runner: &Runner, req: Message) {
let typ = req.body.typ.as_str(); let typ = req.body.typ.as_str();
@ -37,34 +30,26 @@ impl Node for Counter {
let delta = req.body.payload.get("delta").unwrap().as_i64().unwrap(); let delta = req.body.payload.get("delta").unwrap().as_i64().unwrap();
loop { loop {
let cur = kv.read(runner, KEY).unwrap().unwrap().as_i64().unwrap(); let cur = kv.read(runner, KEY).unwrap().unwrap().as_i64().unwrap();
let cur = cur.max(self.0);
let new = cur + delta; let new = cur + delta;
match kv.cas(runner, KEY, cur.into(), new.into(), false) { if kv.cas(runner, KEY, cur.into(), new.into(), false).is_ok() {
Err(_e) => {} break;
Ok(_) => {
let nodes = runner
.nodes()
.iter()
.filter(|e| e != &&runner.node_id())
.collect::<Vec<_>>();
self.0 = new;
gossip(&nodes, runner, new);
break;
}
} }
} }
runner.reply(&req, Body::from_type("add_ok")); runner.reply(&req, Body::from_type("add_ok"));
} }
"read" => { "read" => {
let val = self.0; let mut rounds = 0;
let body = let mut val = Value::Null;
Body::from_type("read_ok").with_payload(mk_payload(&[("value", val.into())])); while rounds < 2 {
runner.reply(&req, body); let v = kv.read(runner, KEY).unwrap().unwrap();
} if kv.cas(runner, KEY, v.clone(), v.clone(), false).is_ok() {
rounds += 1;
}
val = v;
}
"gossip" => { let body = Body::from_type("read_ok").with_payload(mk_payload(&[("value", val)]));
let val = req.body.payload.get("goss").unwrap().as_i64().unwrap(); runner.reply(&req, body);
self.0 = val.max(self.0);
} }
_ => { _ => {
eprintln!("unknown type: {req:?}"); eprintln!("unknown type: {req:?}");