All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.sinri.keel.redis.mixin.RedisApiMixin Maven / Gradle / Ivy

Go to download

A website framework with VERT.X for ex-PHP-ers, exactly Ark Framework Users.

The newest version!
package io.github.sinri.keel.redis.mixin;

import io.vertx.core.Future;
import io.vertx.redis.client.Redis;
import io.vertx.redis.client.RedisAPI;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @since 3.0.5
 */
public interface RedisApiMixin {
    Redis getClient();

    Future api();

    /**
     * EXISTS key [key ...]
     * 从 Redis 3.0.3 起可以一次检查多个 key 是否存在。这种情况下,返回待检查 key 中存在的 key 的个数。检查单个 key 返回 1 或 0 。
     * 注意:如果相同的 key 在参数列表中出现了多次,它会被计算多次。所以,如果somekey存在, EXISTS somekey somekey 命令返回 2。
     */
    default Future doesKeyExist(String key) {
        return api().compose(api -> {
            return api.exists(List.of(key))
                    .compose(response -> {
                        Objects.requireNonNull(response);
                        return Future.succeededFuture(response.toInteger() == 1);
                    });
        });
    }

    /**
     * EXISTS key [key ...]
     * 从 Redis 3.0.3 起可以一次检查多个 key 是否存在。这种情况下,返回待检查 key 中存在的 key 的个数。检查单个 key 返回 1 或 0 。
     * 注意:如果相同的 key 在参数列表中出现了多次,它会被计算多次。所以,如果somekey存在, EXISTS somekey somekey 命令返回 2。
     */
    default Future countExistedKeys(List keys) {
        return api().compose(api -> {
            return api.exists(keys)
                    .compose(response -> {
                        Objects.requireNonNull(response);
                        return Future.succeededFuture(response.toInteger());
                    });
        });
    }

    /**
     * DEL key [key ...]
     * Redis DEL 命令用于删除给定的一个或多个 key 。
     * 不存在的 key 会被忽略。
     *
     * @return 被删除 key 的数量。
     */
    default Future deleteKeys(List keys) {
        return api().compose(api -> {
            return api.del(keys)
                    .compose(response -> {
                        return Future.succeededFuture(response.toInteger());
                    });
        });
    }

    default Future deleteKey(String key) {
        return deleteKeys(List.of(key));
    }

    /**
     * UNLINK key [key ...]
     * Redis UNLINK 命令跟 DEL 命令十分相似:用于删除指定的 key 。就像 DEL 一样,如果 key 不存在,则将其忽略。但是,该命令会执行命令之外的线程中执行实际的内存回收,因此它不是阻塞,而 DEL 是阻塞的。这就是命令名称的来源:UNLINK 命令只是将键与键空间断开连接。实际的删除将稍后异步进行。
     *
     * @return 被删除 key 的数量。
     */
    default Future unlinkKeys(List keys) {
        return api().compose(api -> {
            return api.unlink(keys)
                    .compose(response -> {
                        return Future.succeededFuture(response.toInteger());
                    });
        });
    }

    default Future unlinkKey(String key) {
        return unlinkKeys(List.of(key));
    }

    /**
     * TYPE key
     * 以字符串的形式返回存储在 key 中的值的类型。
     * 可返回的类型是: string, list, set, zset,hash 和 stream。
     */
    default Future getValueTypeOfKey(String key) {
        return api().compose(api -> {
            return api.type(key)
                    .compose(response -> {
                        Objects.requireNonNull(response);
                        String x = response.toString();
                        return Future.succeededFuture(ValueType.valueOf(x));
                    });
        });
    }

    /**
     * RANDOMKEY
     * Redis RANDOMKEY 命令从当前数据库中随机返回一个 key 。
     */
    default Future randomKey() {
        return api().compose(api -> {
            return api.randomkey().compose(response -> {
                if (response == null) {
                    return Future.succeededFuture(null);
                } else {
                    return Future.succeededFuture(response.toString());
                }
            });
        });
    }

    enum ValueType {
        string, list, set, zset, hash, stream, none
    }

    /**
     * EXPIRE key seconds
     * 设置 key 的过期时间(seconds)。 设置的时间过期后,key 会被自动删除。带有超时时间的 key 通常被称为易失的(volatile)。
     * 超时时间只能使用删除 key 或者覆盖 key 的命令清除,包括 DEL, SET, GETSET 和所有的 *STORE 命令。 对于修改 key 中存储的值,而不是用新值替换旧值的命令,不会修改超时时间。例如,自增 key 中存储的值的 INCR , 向list中新增一个值 LPUSH, 或者修改 hash 域的值 HSET ,这些都不会修改 key 的过期时间。
     * 通过使用 PERSIST 命令把 key 改回持久的(persistent) key,这样 key 的过期时间也可以被清除。
     * key使用 RENAME 改名后,过期时间被转移到新 key 上。
     * 已存在的旧 key 使用 RENAME 改名,那么新 key 会继承所有旧 key 的属性。例如,一个名为 KeyA 的 key 使用命令 RENAME Key_B Key_A 改名,新的 KeyA 会继承包括超时时间在内的所有 Key_B 的属性。
     * 特别注意,使用负值调用 EXPIRE/PEXPIRE 或使用过去的时间调用 EXPIREAT/PEXPIREAT ,那么 key 会被删除 deleted 而不是过期。 (因为, 触发的key event 将是 del, 而不是 expired).
     */
    default Future expire(String key, int seconds) {
        return api().compose(api -> {
            return api.expire(List.of(key, String.valueOf(seconds)))
                    .compose(response -> {
                        return Future.succeededFuture();
                    });
        });
    }

    /**
     * EXPIREAT key timestamp
     * 详细语义功能说明可以参考 EXPIRE。
     * 使用过去的时间戳将会立即删除该 key。
     *
     * @param unixTimestampInSecond 绝对 Unix 时间戳 (自1970年1月1日以来的秒数)
     */
    default Future expireAt(String key, int unixTimestampInSecond) {
        return api().compose(api -> {
            return api.expireat(List.of(key, String.valueOf(unixTimestampInSecond)))
                    .compose(response -> {
                        return Future.succeededFuture();
                    });
        });
    }

    /**
     * PEXPIRE key milliseconds
     * PEXPIRE 跟 EXPIRE 基本一样,只是过期时间单位是毫秒。
     */
    default Future expireInMillisecond(String key, long milliseconds) {
        return api().compose(api -> {
            return api.pexpire(List.of(key, String.valueOf(milliseconds)))
                    .compose(response -> {
                        return Future.succeededFuture();
                    });
        });
    }

    /**
     * PEXPIREAT key milliseconds-timestamp
     * Redis PEXPIREAT 命令用于设置 key 的过期时间,时间的格式是uinx时间戳并精确到毫秒。
     */
    default Future expireAtInMillisecond(String key, long unixTimestampInMilliseconds) {
        return api().compose(api -> {
            return api.pexpireat(List.of(key, String.valueOf(unixTimestampInMilliseconds)))
                    .compose(response -> {
                        return Future.succeededFuture();
                    });
        });
    }

    /**
     * PTTL key
     * Redis PTTL 命令以毫秒为单位返回 key 的剩余过期时间。
     */
    default Future getTTLInMillisecond(String key) {
        return api().compose(api -> {
            return api.pttl(key)
                    .compose(response -> {
                        var ttl = response.toLong();
                        if (ttl < 0) {
                            // Redis 2.6 之前的版本如果 key 不存在或者 key 没有关联超时时间则返回 -1 。
                            //Redis 2.8 起://key 不存在返回 -2 //key 存在但是没有关联超时时间返回 -1
                            return Future.failedFuture(new RuntimeException("key 不存在或者 key 没有关联超时时间"));
                        }
                        return Future.succeededFuture();
                    });
        });
    }

    /**
     * TTL key
     * Redis TTL 命令以秒为单位返回 key 的剩余过期时间。用户客户端检查 key 还可以存在多久。
     */
    default Future getTTLInSecond(String key) {
        return api().compose(api -> {
            return api.ttl(key)
                    .compose(response -> {
                        var ttl = response.toLong();
                        if (ttl < 0) {
                            // Redis 2.6 之前的版本如果 key 不存在或者 key 没有关联超时时间则返回 -1 。
                            //Redis 2.8 起://key 不存在返回 -2 //key 存在但是没有关联超时时间返回 -1
                            return Future.failedFuture(new RuntimeException("key 不存在或者 key 没有关联超时时间"));
                        }
                        return Future.succeededFuture();
                    });
        });
    }

    /**
     * PERSIST key
     * Redis PERSIST 命令用于删除给定 key 的过期时间,使得 key 永不过期。
     */
    default Future persist(String key) {
        return api().compose(api -> {
            return api.persist(key).compose(response -> {
                return Future.succeededFuture();
            });
        });
    }

    /**
     * KEYS pattern
     * Redis KEYS 命令用于查找所有匹配给定模式 pattern 的 key 。
     * 尽管这个操作的时间复杂度是 O(N),但是常量时间相当小。
     * 例如,在一个普通笔记本上跑 Redis,扫描 100 万个 key 只要40毫秒。
     * Warning: 生产环境使用 KEYS 命令需要非常小心。在大的数据库上执行命令会影响性能。
     * 这个命令适合用来调试和特殊操作,像改变键空间布局。
     * 不要在你的代码中使用 KEYS 。如果你需要一个寻找键空间中的key子集,考虑使用 SCAN 或 sets。
     * 匹配模式:
     * h?llo 匹配 hello, hallo 和 hxllo
     * h*llo 匹配 hllo 和 heeeello
     * h[ae]llo 匹配 hello and hallo, 不匹配 hillo
     * h[^e]llo 匹配 hallo, hbllo, ... 不匹配 hello
     * h[a-b]llo 匹配 hallo 和 hbllo
     * 使用 \ 转义你想匹配的特殊字符。
     */
    default Future> keys(String pattern) {
        return api().compose(api -> {
            return api.keys(pattern).compose(response -> {
                List list = new ArrayList<>();
                response.forEach(x -> {
                    list.add(x.toString());
                });
                return Future.succeededFuture(list);
            });
        });
    }

    /**
     * RENAME key newkey
     * 修改 key 的名字为 newkey 。若key 不存在返回错误。
     * 在集群模式下,key 和newkey 需要在同一个 hash slot。key 和newkey有相同的 hash tag 才能重命名。
     * 如果 newkey 存在则会被覆盖,此种情况隐式执行了 DEL 操作,所以如果要删除的key的值很大会有一定的延时,即使RENAME 本身是常量时间复杂度的操作。
     * 在集群模式下,key 和newkey 需要在同一个 hash slot。key 和newkey有相同的 hash tag 才能重命名。
     */
    default Future renameKey(String oldKey, String newKey) {
        return api().compose(api -> {
            return api.rename(oldKey, newKey).compose(response -> {
                if ("OK".equals(response.toString())) {
                    return Future.succeededFuture();
                } else {
                    throw new RuntimeException(response.toString());
                }
            });
        });
    }

    /**
     * RENAMENX key newkey
     * Redis Renamenx 命令用于在新的 key 不存在时修改 key 的名称 。若 key 不存在返回错误。
     * 在集群模式下,key 和newkey 需要在同一个 hash slot。key 和newkey有相同的 hash tag 才能重命名。
     */
    default Future renameKeyIfNewKeyNotExists(String oldKey, String newKey) {
        return api().compose(api -> {
            return api.renamenx(oldKey, newKey).compose(response -> {
                if ("OK".equals(response.toString())) {
                    return Future.succeededFuture();
                } else {
                    throw new RuntimeException(response.toString());
                }
            });
        });
    }

    /**
     * TOUCH key [key ...]
     * 修改指定 key 的 最后访问时间。忽略不存在的 key。
     *
     * @return 被更新的 key 个数
     */
    default Future touch(List keys) {
        return api().compose(api -> {
            return api.touch(keys).compose(response -> {
                return Future.succeededFuture(response.toInteger());
            });
        });
    }

    // todo
    //  DUMP key
    //  RESTORE key ttl serialized-value [REPLACE] [ABSTTL] [IDLETIME seconds] [FREQ frequency]
    //  MIGRATE host port key|"" destination-db timeout [COPY] [REPLACE] [AUTH password] [AUTH2 username password] [KEYS key [key ...]]
    //  MOVE key db
    //  OBJECT subcommand [arguments [arguments ...]]
    //  SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]
    //  SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination]
    //  WAIT numreplicas timeout
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy