Skip to content

Commit

Permalink
Add expiration variants: EXAT,PXAT
Browse files Browse the repository at this point in the history
  • Loading branch information
ogzhanolguncu committed Sep 11, 2023
1 parent 12e6fae commit 00ee46e
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 20 deletions.
42 changes: 42 additions & 0 deletions src/connection_manager/command_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ pub fn handle_command(human_readable: Cow<'_, str>, cache: &Cache) -> String {

#[cfg(test)]
mod tests {
use std::{thread, time::Duration};

use crate::{
connection_manager::utils::throw_err_if_num_of_args_wrong,
resp::serialize::{serialize, InputVariants},
Expand Down Expand Up @@ -110,4 +112,44 @@ mod tests {
handle_command(input, &cache)
);
}

#[test]
fn should_set_with_expiration_and_retrive_expired() {
let cache = Cache::new();
let set_input = Cow::Borrowed(
"*5\r\n$3\r\nset\r\n$4\r\nname\r\n$12\r\nWizard of Oz\r\n$2\r\nEX\r\n$1\r\n3",
);
let get_input = Cow::Borrowed("*2\r\n$3\r\nget\r\n$4\r\nname\r\n");
handle_command(set_input, &cache);
thread::sleep(Duration::from_secs(4));

assert_eq!(
serialize(InputVariants::StringVariant("+(nil)".to_string())),
handle_command(get_input, &cache)
);
}

#[test]
fn should_set_with_unknown_expiration_variant() {
let cache = Cache::new();
let set_input = Cow::Borrowed(
"*5\r\n$3\r\nset\r\n$4\r\nname\r\n$12\r\nWizard of Oz\r\n$6\r\nEXATAT\r\n$1\r\n3",
);
assert_eq!(
serialize_error("-unknown SET variant"),
handle_command(set_input, &cache)
);
}

#[test]
fn should_set_with_unparseable_value() {
let cache = Cache::new();
let set_input = Cow::Borrowed(
"*5\r\n$3\r\nset\r\n$4\r\nname\r\n$12\r\nWizard of Oz\r\n$6\r\nEXATAT\r\n$3\r\nAAA",
);
assert_eq!(
serialize_error("-invalid SET expiration"),
handle_command(set_input, &cache)
);
}
}
51 changes: 31 additions & 20 deletions src/connection_manager/commands.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use std::time::{Duration, SystemTime, UNIX_EPOCH};

use crate::{
resp::serialize::{serialize, InputVariants},
Expand Down Expand Up @@ -30,7 +30,7 @@ pub fn handle_get(args: &[String], cache: &Cache) -> String {
serialize(InputVariants::StringVariant("+(nil)".to_string()))
}
} else {
serialize_error("-ERR Invalid GET arguments")
serialize_error("-invalid GET arguments")
}
}

Expand All @@ -45,27 +45,38 @@ pub fn handle_set(args: &[String], cache: &Cache) -> String {
match exp_variant.clone().as_str() {
"EX" => handle_set_with_expiration(args, cache, Duration::from_secs(time)),
"PX" => handle_set_with_expiration(args, cache, Duration::from_millis(time)),
// "EXAT" => {
// let now = SystemTime::now();
// let now_unix = now
// .duration_since(UNIX_EPOCH)
// .expect("Time went backwards")
// .as_secs();
// let duration_until_expiration = Duration::from_secs(time - now_unix);

// }
_ => todo!(),
"EXAT" => {
let now = SystemTime::now();
let now_unix = now
.duration_since(UNIX_EPOCH)
.expect("Impossibru!")
.as_secs();
handle_set_with_expiration(args, cache, Duration::from_secs(time - now_unix))
}
"PXAT" => {
let now = SystemTime::now();
let now_unix = now
.duration_since(UNIX_EPOCH)
.expect("Impossibru!")
.as_millis() as u64;
handle_set_with_expiration(args, cache, Duration::from_millis(time - now_unix))
}
_ => serialize_error("-unknown SET variant"),
}
} else {
serialize_error("-ERR Invalid SET expiration")
serialize_error("-invalid SET expiration")
}
} else {
if let (Some(key), Some(value)) = (args.get(0), args.get(1)) {
cache.set(key.clone(), value.clone());
serialize(InputVariants::StringVariant("+OK".to_string()))
} else {
serialize_error("-ERR Invalid SET arguments")
}
handle_set_without_expiration(args, cache)
}
}

fn handle_set_without_expiration(args: &[String], cache: &Cache) -> String {
if let (Some(key), Some(value)) = (args.get(0), args.get(1)) {
cache.set(key.clone(), value.clone());
serialize(InputVariants::StringVariant("+OK".to_string()))
} else {
serialize_error("-invalid SET arguments")
}
}

Expand All @@ -74,6 +85,6 @@ fn handle_set_with_expiration(args: &[String], cache: &Cache, time: Duration) ->
cache.set_with_expiration(key.clone(), value.clone(), time);
serialize(InputVariants::StringVariant("+OK".to_string()))
} else {
serialize_error("-ERR Invalid SET arguments")
serialize_error("-invalid SET arguments")
}
}
12 changes: 12 additions & 0 deletions src/store/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,16 @@ mod tests {
cache.set(String::from("name"), String::from("The Wizard of Oz"));
assert_eq!("The Wizard of Oz", cache.get("name").unwrap());
}

#[test]
fn should_set_and_get_expiration() {
let cache = Cache::new();
cache.set_with_expiration(
String::from("name"),
String::from("The Wizard of Oz"),
Duration::from_secs(3),
);
thread::sleep(Duration::from_secs(4));
assert!(cache.get("name").is_none());
}
}

0 comments on commit 00ee46e

Please sign in to comment.