Skip to content

Commit 812ab4b

Browse files
committed
cleanup and integration testing
1 parent 80ae411 commit 812ab4b

File tree

5 files changed

+45
-38
lines changed

5 files changed

+45
-38
lines changed

build.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,6 @@ impl ParseCallbacks for RedisModuleCallback {
1414
Some(IntKind::U64)
1515
} else if name.starts_with("REDISMODULE_REPLY") {
1616
Some(IntKind::I32)
17-
} else if name == "REDISMODULE_LIST_HEAD"
18-
|| name == "REDISMODULE_LIST_TAIL"
19-
{
20-
// These values are used as `enum` discriminants, and thus must be `isize`.
21-
Some(IntKind::Custom {
22-
name: "isize",
23-
is_signed: true,
24-
})
2517
} else if name.starts_with("REDISMODULE_NOTIFY_") {
2618
Some(IntKind::Int)
2719
} else {

src/context/key_scan_cursor.rs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,6 @@ impl ScanKeyCursor {
9999
}
100100

101101
pub fn iter(&self) -> ScanKeyCursorIterator<'_> {
102-
let ctx = Context::new(self.key.ctx);
103-
ctx.log_notice("Starting ScanKeyCursor iteration");
104102
ScanKeyCursorIterator {
105103
cursor: self,
106104
buf: Vec::new(),
@@ -117,6 +115,7 @@ impl Drop for ScanKeyCursor {
117115

118116
pub type ScanKeyIteratorItem = (RedisString, RedisString);
119117

118+
/// An iterator (state) over the field/value pairs of a hash key.
120119
pub struct ScanKeyCursorIterator<'a> {
121120
/// The cursor that is used for the iteration
122121
cursor: &'a ScanKeyCursor,
@@ -233,34 +232,25 @@ unsafe extern "C" fn iterator_callback(
233232
value: *mut raw::RedisModuleString,
234233
data: *mut c_void,
235234
) {
236-
// SAFETY: this is the responsibility of the caller, see only usage below in `next()`
237-
// `data` is a stack slot of type Data
235+
// `data` is a stack slot
238236
let slot = data.cast::<StackSlot>();
239237
let slot = &mut (*slot);
240238

241-
// todo: use new-type with refcount handling for better performance
239+
// todo: use new-type with refcount handling for better performance, otherwise we have to copy at this point
240+
// we know that this callback will be called in a loop scope and that we
241+
// need to store the RedisString longer than the ScanKey invocation but not much
242+
// longer and in case of batched results we don't need to store everything in memory
243+
// but only the last batch.
242244
let field = raw::RedisModule_CreateStringFromString.unwrap()(slot.ctx.get_raw(), field);
243245
let value = raw::RedisModule_CreateStringFromString.unwrap()(slot.ctx.get_raw(), value);
244246

245247
let field = RedisString::from_redis_module_string(slot.ctx.get_raw(), field);
246248
let value = RedisString::from_redis_module_string(slot.ctx.get_raw(), value);
247249

248-
if slot.buf.is_empty() {
249-
let out = format!("CB - Value tu return - Field: {}, Value: {}", field, value);
250-
slot.ctx.log_notice(&out);
251-
} else {
252-
// This is the case where the callback is called multiple times.
253-
// We need to buffer the data in the iterator state.
254-
let out = format!(
255-
"CB - Buffer for future use - Field: {}, Value: {}",
256-
field, value
257-
);
258-
slot.ctx.log_notice(&out);
259-
}
260250
slot.buf.push((field, value));
261251
}
262252

263-
// Implements an iterator for `KeysCursor` that yields (RedisKey, *mut RedisModuleString, *mut RedisModuleString) in a Rust for loop.
253+
// Implements an iterator for `KeysCursor` that yields (RedisString, RedisString) in a Rust for loop.
264254
// This is a wrapper around the RedisModule_ScanKey function from the C API and uses a pattern to get the values from the callback that
265255
// is also used in stack unwinding scenarios. There is not common term for that but here we can think of it as a "stack slot" pattern.
266256
impl Iterator for ScanKeyCursorIterator<'_> {

src/raw.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,6 @@ bitflags! {
2929
pub struct KeyMode: c_int {
3030
const READ = REDISMODULE_READ as c_int;
3131
const WRITE = REDISMODULE_WRITE as c_int;
32-
33-
const KEYOPEN_NOTOUCH = REDISMODULE_OPEN_KEY_NOTOUCH as c_int;
34-
const KEYOPEN_NONOTIFY = REDISMODULE_OPEN_KEY_NONOTIFY as c_int;
35-
const KEYOPEN_NOSTATS = REDISMODULE_OPEN_KEY_NOSTATS as c_int;
36-
const KEYOPEN_NOEFFECTS = REDISMODULE_OPEN_KEY_NOEFFECTS as c_int;
37-
const KEYOPEN_NOEXPIRE = REDISMODULE_OPEN_KEY_NOEXPIRE as c_int;
38-
const KEYOPEN_ACCESSEXPIRED = REDISMODULE_OPEN_KEY_ACCESS_EXPIRED as c_int;
3932
}
4033
}
4134

@@ -60,7 +53,8 @@ pub enum KeyType {
6053
Stream = REDISMODULE_KEYTYPE_STREAM,
6154
}
6255

63-
#[derive(Primitive, Debug, PartialEq, Eq)]
56+
#[repr(u32)]
57+
#[derive(Primitive, Debug, PartialEq, Eq, strum::FromRepr)]
6458
pub enum Where {
6559
ListHead = REDISMODULE_LIST_HEAD,
6660
ListTail = REDISMODULE_LIST_TAIL,

src/redismodule.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,10 +273,6 @@ impl RedisString {
273273
impl Drop for RedisString {
274274
fn drop(&mut self) {
275275
if !self.inner.is_null() {
276-
let ctx = Context::new(self.ctx);
277-
let out = format!("Dropping RedisString '{}'", self.to_string_lossy());
278-
ctx.log_notice(&out);
279-
280276
unsafe {
281277
raw::RedisModule_FreeString.unwrap()(self.ctx, self.inner);
282278
}

tests/integration.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,41 @@ fn test_scan() -> Result<()> {
200200
Ok(())
201201
}
202202

203+
#[test]
204+
fn test_scan_key_it() -> Result<()> {
205+
let mut con = TestConnection::new("scan_keys");
206+
207+
redis::cmd("hset")
208+
.arg(&[
209+
"user:123", "name", "Alice", "age", "29", "location", "Austin",
210+
])
211+
.query::<()>(&mut con)
212+
.with_context(|| "failed to hset")?;
213+
214+
let res: Vec<String> = redis::cmd("scan_key_it")
215+
.arg(&["user:123"])
216+
.query(&mut con)?;
217+
assert_eq!(&res, &["name", "Alice", "age", "29", "location", "Austin"]);
218+
Ok(())
219+
}
220+
221+
#[test]
222+
fn test_scan_key_foreach() -> Result<()> {
223+
let mut con = TestConnection::new("scan_keys");
224+
redis::cmd("hset")
225+
.arg(&[
226+
"user:123", "name", "Alice", "age", "29", "location", "Austin",
227+
])
228+
.query::<()>(&mut con)
229+
.with_context(|| "failed to hset")?;
230+
231+
let res: Vec<String> = redis::cmd("scan_key_fe")
232+
.arg(&["user:123"])
233+
.query(&mut con)?;
234+
assert_eq!(&res, &["name", "Alice", "age", "29", "location", "Austin"]);
235+
Ok(())
236+
}
237+
203238
#[test]
204239
fn test_stream_reader() -> Result<()> {
205240
let mut con = TestConnection::new("stream");

0 commit comments

Comments
 (0)