shardmap 0.3.1

Sharded embedded in-memory map with optional cache, protocol, and server internals
Documentation
use bytes::BytesMut;

use crate::commands::redis::{
    bulk, define_redis_command, write_frame, write_resp_null, wrong_arity,
};
use crate::protocol::Frame;
#[cfg(feature = "server")]
use crate::server::wire::ServerWire;
use crate::storage::{DEFAULT_SCAN_COUNT, EmbeddedStore, RedisKeyScanType, now_millis};

define_redis_command!(RandomKey, "RANDOMKEY", false);

impl crate::commands::redis::RedisCommand for RandomKey {
    fn execute(store: &EmbeddedStore, args: &[&[u8]]) -> Frame {
        if !args.is_empty() {
            return wrong_arity("RANDOMKEY");
        }
        match random_key_bytes(store) {
            Some(key) => bulk(key),
            None => Frame::Null,
        }
    }

    #[cfg(feature = "server")]
    fn write_resp(store: &EmbeddedStore, args: &[&[u8]], out: &mut BytesMut) {
        if !args.is_empty() {
            write_frame(out, &wrong_arity("RANDOMKEY"));
            return;
        }
        match random_key_bytes(store) {
            Some(key) => ServerWire::write_resp_blob_string(out, &key),
            None => write_resp_null(out),
        }
    }
}

fn random_key_bytes(store: &EmbeddedStore) -> Option<Vec<u8>> {
    let shard_count = store.shard_count();
    let start = (now_millis() as usize) % shard_count.max(1);
    for offset in 0..shard_count {
        let shard_id = (start + offset) % shard_count;
        let mut found = None;
        let _ = store.scan_redis_keys_in_shard_visit(
            shard_id,
            0,
            DEFAULT_SCAN_COUNT.min(1),
            RedisKeyScanType::All,
            &mut |key| {
                found = Some(key.to_vec());
                true
            },
        );
        if found.is_some() {
            return found;
        }
    }
    None
}