From ac5477d1d053d1e600012c68c4e38e7ff4f8d60d Mon Sep 17 00:00:00 2001 From: Joe Ardent Date: Sun, 9 Jun 2024 13:07:32 -0700 Subject: [PATCH] passes 6a, totally available single node --- Cargo.lock | 8 ++++ Cargo.toml | 2 +- gg-txn/Cargo.toml | 10 +++++ gg-txn/src/main.rs | 110 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 gg-txn/Cargo.toml create mode 100644 gg-txn/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 9de2658..51df713 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -53,6 +53,14 @@ dependencies = [ "serde_json", ] +[[package]] +name = "gg-txn" +version = "0.0.1" +dependencies = [ + "nebkor-maelstrom", + "serde_json", +] + [[package]] name = "gg-uid" version = "0.0.1" diff --git a/Cargo.toml b/Cargo.toml index 1d66af7..648d9cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["gg-echo", "gg-uid", "gg-broadcast", "gg-g_counter", "gg-kafka"] +members = ["gg-echo", "gg-uid", "gg-broadcast", "gg-g_counter", "gg-kafka", "gg-txn"] resolver = "2" [workspace.package] diff --git a/gg-txn/Cargo.toml b/gg-txn/Cargo.toml new file mode 100644 index 0000000..c30c014 --- /dev/null +++ b/gg-txn/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "gg-txn" +edition = "2021" +version.workspace = true +authors.workspace = true +license-file.workspace = true + +[dependencies] +nebkor-maelstrom.workspace = true +serde_json.workspace = true diff --git a/gg-txn/src/main.rs b/gg-txn/src/main.rs new file mode 100644 index 0000000..b751400 --- /dev/null +++ b/gg-txn/src/main.rs @@ -0,0 +1,110 @@ +use std::collections::HashMap; + +use nebkor_maelstrom::{mk_payload, Body, Message, Node, Runner}; +use serde_json::Value; + +type Txn = Vec; + +trait TxnSer { + fn serialize(&self) -> Value; +} + +impl TxnSer for Txn { + fn serialize(&self) -> Value { + let out: Vec = self + .iter() + .map(|t| { + let v: Vec = vec![t.op.clone().into(), t.key.into(), t.value.into()]; + v.into() + }) + .collect(); + out.into() + } +} + +fn main() { + let node = TANode::default(); + let runner = Runner::new(node); + runner.run(None); +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +struct TxnOp { + op: String, + key: u64, + value: Option, +} + +#[derive(Debug, Clone, Default)] +struct TANode { + store: HashMap, +} + +impl TANode { + fn transact(&mut self, txn: &Txn) -> Txn { + let mut out = Txn::with_capacity(txn.len()); + for txn_op in txn.iter() { + let op = txn_op.op.as_str(); + match op { + "r" => { + let key = txn_op.key; + let op = TxnOp { + op: "r".into(), + key, + value: self.store.get(&key).cloned(), + }; + out.push(op); + } + "w" => { + self.store.insert(txn_op.key, txn_op.value.unwrap()); + out.push(txn_op.clone()); + } + _ => { + eprintln!("unknown TxnOp op {op}"); + } + } + } + + out + } +} + +impl Node for TANode { + fn handle(&mut self, runner: &Runner, msg: Message) { + let typ = msg.typ(); + + match typ { + "txn" => { + let txn = get_txn(&msg); + + let txn = self.transact(&txn); + + let payload = mk_payload(&[("txn", txn.serialize())]); + let body = Body::from_type("txn_ok").with_payload(payload); + runner.reply(&msg, body); + } + _ => { + eprintln!("unknown message type {typ}") + } + } + } +} + +fn get_txn(msg: &Message) -> Txn { + msg.body + .payload + .get("txn") + .unwrap() + .as_array() + .unwrap() + .iter() + .map(|e| { + let o = e.as_array().unwrap(); + TxnOp { + op: o[0].as_str().unwrap().to_string(), + key: o[1].as_u64().unwrap(), + value: o[2].as_u64(), + } + }) + .collect() +}