don't use internal state in the node
This commit is contained in:
parent
7a0147f88e
commit
23b95677bf
1 changed files with 16 additions and 31 deletions
|
@ -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:?}");
|
||||||
|
|
Loading…
Reference in a new issue