inspectRedisKey function

Future<Map<String, Object?>> inspectRedisKey(
  1. RedisClient client,
  2. String key, {
  3. bool values = true,
  4. int limit = 20,
})

What one key holds: its type, time to live, encoding, size and memory, and with values the first limit items (a string's first 1000 characters). Null fields where the server does not say.

Implementation

Future<Map<String, Object?>> inspectRedisKey(
  RedisClient client,
  String key, {
  bool values = true,
  int limit = 20,
}) async {
  final type = '${await client.command(['TYPE', key])}';
  if (type == 'none') {
    return {'key': key, 'exists': false};
  }
  Future<Object?> optional(List<Object?> args) async {
    try {
      return await client.command(args);
    } on RedisCommandException {
      return null;
    }
  }

  final size = switch (type) {
    'string' => ['STRLEN', key],
    'hash' => ['HLEN', key],
    'list' => ['LLEN', key],
    'set' => ['SCARD', key],
    'zset' => ['ZCARD', key],
    'stream' => ['XLEN', key],
    _ => null,
  };
  final preview = !values
      ? null
      : switch (type) {
          'string' => switch (await client.get(key)) {
            final String text when text.length > 1000 =>
              '${text.substring(0, 1000)}…',
            final value => value,
          },
          'hash' =>
            ((await client.command(['HSCAN', key, 0, 'COUNT', limit]))!
                as List)[1],
          'list' => await client.command(['LRANGE', key, 0, limit - 1]),
          'set' =>
            ((await client.command(['SSCAN', key, 0, 'COUNT', limit]))!
                as List)[1],
          'zset' => await client.command([
            'ZRANGE',
            key,
            0,
            limit - 1,
            'WITHSCORES',
          ]),
          'stream' => await client.command([
            'XREVRANGE',
            key,
            '+',
            '-',
            'COUNT',
            limit,
          ]),
          _ => null,
        };
  return {
    'key': key,
    'exists': true,
    'type': type,
    'ttl_ms': await client.command(['PTTL', key]),
    'encoding': await optional(['OBJECT', 'ENCODING', key]),
    'size': size == null ? null : await client.command(size),
    'memory_bytes': await optional(['MEMORY', 'USAGE', key]),
    'values': values ? preview : 'hidden in production',
  };
}