Better handling of causal context parse errors
Some checks failed
continuous-integration/drone/pr Build is failing
continuous-integration/drone/push Build is failing

This commit is contained in:
Alex 2022-04-28 11:44:20 +02:00
parent fdbed3f1e8
commit 754919170f
Signed by: lx
GPG key ID: 0E496D15096376BE
3 changed files with 15 additions and 17 deletions

View file

@ -133,7 +133,8 @@ pub async fn handle_insert_item(
.map(|s| s.to_str()) .map(|s| s.to_str())
.transpose()? .transpose()?
.map(CausalContext::parse) .map(CausalContext::parse)
.transpose()?; .transpose()
.ok_or_bad_request("Invalid causality token")?;
let body = hyper::body::to_bytes(req.into_body()).await?; let body = hyper::body::to_bytes(req.into_body()).await?;
let value = DvvsValue::Value(body.to_vec()); let value = DvvsValue::Value(body.to_vec());
@ -167,7 +168,8 @@ pub async fn handle_delete_item(
.map(|s| s.to_str()) .map(|s| s.to_str())
.transpose()? .transpose()?
.map(CausalContext::parse) .map(CausalContext::parse)
.transpose()?; .transpose()
.ok_or_bad_request("Invalid causality token")?;
let value = DvvsValue::Deleted; let value = DvvsValue::Deleted;
@ -200,13 +202,16 @@ pub async fn handle_poll_item(
) -> Result<Response<Body>, Error> { ) -> Result<Response<Body>, Error> {
let format = ReturnFormat::from(req)?; let format = ReturnFormat::from(req)?;
let causal_context =
CausalContext::parse(&causality_token).ok_or_bad_request("Invalid causality token")?;
let item = garage let item = garage
.k2v_rpc .k2v_rpc
.poll( .poll(
bucket_id, bucket_id,
partition_key, partition_key,
sort_key, sort_key,
causality_token, causal_context,
timeout_secs.unwrap_or(300) * 1000, timeout_secs.unwrap_or(300) * 1000,
) )
.await?; .await?;

View file

@ -4,7 +4,6 @@ use std::convert::TryInto;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use garage_util::data::*; use garage_util::data::*;
use garage_util::error::*;
/// Node IDs used in K2V are u64 integers that are the abbreviation /// Node IDs used in K2V are u64 integers that are the abbreviation
/// of full Garage node IDs which are 256-bit UUIDs. /// of full Garage node IDs which are 256-bit UUIDs.
@ -45,13 +44,11 @@ impl CausalContext {
base64::encode_config(bytes, base64::URL_SAFE_NO_PAD) base64::encode_config(bytes, base64::URL_SAFE_NO_PAD)
} }
/// Parse from base64-encoded binary representation /// Parse from base64-encoded binary representation
pub fn parse(s: &str) -> Result<Self, Error> { pub fn parse(s: &str) -> Result<Self, String> {
let bytes = base64::decode_config(s, base64::URL_SAFE_NO_PAD) let bytes = base64::decode_config(s, base64::URL_SAFE_NO_PAD)
.ok_or_message("Invalid causality token (bad base64)")?; .map_err(|e| format!("bad causality token base64: {}", e))?;
if bytes.len() % 16 != 8 || bytes.len() < 8 { if bytes.len() % 16 != 8 || bytes.len() < 8 {
return Err(Error::Message( return Err("bad causality token length".into());
"Invalid causality token (bad length)".into(),
));
} }
let checksum = u64::from_be_bytes(bytes[..8].try_into().unwrap()); let checksum = u64::from_be_bytes(bytes[..8].try_into().unwrap());
@ -68,9 +65,7 @@ impl CausalContext {
let check = ret.vector_clock.iter().fold(0, |acc, (n, t)| acc ^ *n ^ *t); let check = ret.vector_clock.iter().fold(0, |acc, (n, t)| acc ^ *n ^ *t);
if check != checksum { if check != checksum {
return Err(Error::Message( return Err("bad causality token checksum".into());
"Invalid causality token (bad checksum)".into(),
));
} }
Ok(ret) Ok(ret)

View file

@ -38,7 +38,7 @@ enum K2VRpc {
InsertManyItems(Vec<InsertedItem>), InsertManyItems(Vec<InsertedItem>),
PollItem { PollItem {
key: PollKey, key: PollKey,
causal_context: String, causal_context: CausalContext,
timeout_msec: u64, timeout_msec: u64,
}, },
PollItemResponse(Option<K2VItem>), PollItemResponse(Option<K2VItem>),
@ -189,7 +189,7 @@ impl K2VRpcHandler {
bucket_id: Uuid, bucket_id: Uuid,
partition_key: String, partition_key: String,
sort_key: String, sort_key: String,
causal_context: String, causal_context: CausalContext,
timeout_msec: u64, timeout_msec: u64,
) -> Result<Option<K2VItem>, Error> { ) -> Result<Option<K2VItem>, Error> {
let poll_key = PollKey { let poll_key = PollKey {
@ -295,9 +295,7 @@ impl K2VRpcHandler {
}) })
} }
async fn handle_poll(&self, key: &PollKey, ct: &str) -> Result<K2VItem, Error> { async fn handle_poll(&self, key: &PollKey, ct: &CausalContext) -> Result<K2VItem, Error> {
let ct = CausalContext::parse(ct)?;
let mut chan = self.subscriptions.subscribe(key); let mut chan = self.subscriptions.subscribe(key);
let mut value = self let mut value = self