Skip to content

Commit

Permalink
Merge branch 'master' into impl-pttl
Browse files Browse the repository at this point in the history
  • Loading branch information
ndelvalle authored Oct 21, 2024
2 parents a1a189a + 7db8830 commit b1c8b04
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 16 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ strum = "0.26.2"
strum_macros = "0.26.2"
clap = { version = "4.5.7", features = ["derive", "env"] }
num-traits = "0.2.19"
itertools = "0.13.0"

[dev-dependencies]
rand = "0.8.5"
Expand Down
12 changes: 7 additions & 5 deletions src/commands/keys.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use bytes::Bytes;
use glob_match::glob_match;
use itertools::Itertools;

use crate::commands::executable::Executable;
use crate::commands::CommandParser;
Expand All @@ -20,11 +21,12 @@ pub struct Keys {
impl Executable for Keys {
fn exec(self, store: Store) -> Result<Frame, Error> {
let store = store.lock();
let matching_keys: Vec<Frame> = store
.keys()
.filter(|key| glob_match(self.pattern.as_str(), key))
.map(|key| Frame::Bulk(Bytes::from(key.to_string())))
.collect();
let matching_keys = store
.iter()
.filter(|(key, _)| glob_match(self.pattern.as_str(), key))
.sorted_by(|(_, a), (_, b)| b.created_at.cmp(&a.created_at))
.map(|(key, _)| Frame::Bulk(Bytes::from(key.to_string())))
.collect::<Vec<_>>();

Ok(Frame::Array(matching_keys))
}
Expand Down
18 changes: 11 additions & 7 deletions src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,29 @@ pub struct InnerStoreLocked<'a> {
impl<'a> InnerStoreLocked<'a> {
pub fn set(&mut self, key: String, data: Bytes) {
// Ensure any previous TTL is removed.
self.remove(&key);
let removed = self.remove(&key);

let created_at = removed.map(|v| v.created_at).unwrap_or(Instant::now());

let value = Value {
data,
expires_at: None,
created_at,
};
self.state.keys.insert(key, value);
}

pub fn set_with_ttl(&mut self, key: Key, data: Bytes, ttl: Duration) {
// Ensure any previous TTL is removed.
self.remove(&key);
let removed = self.remove(&key);

let created_at = removed.map(|v| v.created_at).unwrap_or(Instant::now());

let expires_at = Instant::now() + ttl;
let value = Value {
data,
expires_at: Some(expires_at),
created_at,
};

self.state.keys.insert(key.clone(), value);
Expand Down Expand Up @@ -142,11 +148,8 @@ impl<'a> InnerStoreLocked<'a> {
self.state.keys.keys()
}

pub fn iter(&self) -> impl Iterator<Item = (&String, &Bytes)> {
self.state
.keys
.iter()
.map(|(key, value)| (key, &value.data))
pub fn iter(&self) -> impl Iterator<Item = (&String, &Value)> {
self.state.keys.iter().map(|(key, value)| (key, value))
}

pub fn incr_by<T, R>(&mut self, key: &str, increment: T) -> Result<R, String>
Expand Down Expand Up @@ -232,6 +235,7 @@ type Key = String;
pub struct Value {
pub data: Bytes,
pub expires_at: Option<Instant>,
pub created_at: Instant,
}

pub struct State {
Expand Down
15 changes: 11 additions & 4 deletions tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,15 +363,22 @@ async fn test_getrange() {
#[tokio::test]
#[serial]
async fn test_keys() {
// TODO: The response order from the server is not guaranteed, to ensure accurate comparison
// with the expected result, we need to sort the response before performing the comparison.
test_compare::<Vec<Value>>(|p| {
// Redis keys order is deterministic (always returning the same order for
// a given set of keys) but not guaranteed (it may change between runs).
//
// We sort in backward chronological order to get deterministic results.
// Matching the implementation is out of the scope of the project.
p.cmd("SET").arg("keys_key_1").arg("Argentina");
p.cmd("SET").arg("keys_key_2").arg("Spain");
p.cmd("SET").arg("keys_key_3").arg("Netherlands");

p.cmd("KEYS").arg("*");
p.cmd("KEYS").arg("*key*");

p.cmd("SET").arg("keys_key_2").arg("Spain");
p.cmd("SET").arg("keys_key_3").arg("Netherlands");

p.cmd("KEYS").arg("*1");
p.cmd("KEYS").arg("*2");
p.cmd("KEYS").arg("*3");
})
.await;
Expand Down

0 comments on commit b1c8b04

Please sign in to comment.