Implement KeyDB's EXPIREMEMBER[AT] commands

This commit is contained in:
michael-grunder
2024-11-14 21:44:07 -08:00
committed by Michael Grunder
parent 8144db3743
commit 4cd3f59356
11 changed files with 204 additions and 9 deletions

View File

@@ -1379,6 +1379,14 @@ PHP_METHOD(Redis, pexpiretime) {
REDIS_PROCESS_KW_CMD("PEXPIRETIME", redis_key_cmd, redis_long_response);
}
PHP_METHOD(Redis, expiremember) {
REDIS_PROCESS_CMD(expiremember, redis_long_response);
}
PHP_METHOD(Redis, expirememberat) {
REDIS_PROCESS_CMD(expirememberat, redis_long_response);
}
/* }}} */
/* {{{ proto array Redis::lSet(string key, int index, string value) */
PHP_METHOD(Redis, lSet) {

View File

@@ -1903,6 +1903,28 @@ class Redis {
*/
public function hscan(string $key, null|int|string &$iterator, ?string $pattern = null, int $count = 0): Redis|array|bool;
/**
* Set an expiration on a key member (KeyDB only).
*
* @see https://docs.keydb.dev/docs/commands/#expiremember
*
* @param string $key The key to expire
* @param string $field The field to expire
* @param string|null $unit The unit of the ttl (s, or ms).
*/
public function expiremember(string $key, string $field, int $ttl, ?string $unit = null): Redis|int|false;
/**
* Set an expiration on a key membert to a specific unix timestamp (KeyDB only).
*
* @see https://docs.keydb.dev/docs/commands/#expirememberat
*
* @param string $key The key to expire
* @param string $field The field to expire
* @param int $timestamp The unix timestamp to expire at.
*/
public function expirememberat(string $key, string $field, int $timestamp): Redis|int|false;
/**
* Increment a key's value, optionally by a specific amount.
*

View File

@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 1cc5fe0df8dfa7d95f2bc45c2383132a68629f24 */
* Stub hash: bacbe6b1d55da4ba6d370fff1090e8de0363c4c2 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 1, "null")
@@ -464,6 +464,19 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_hscan, 0, 2, Red
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, count, IS_LONG, 0, "0")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_expiremember, 0, 3, Redis, MAY_BE_LONG|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, field, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, ttl, IS_LONG, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, unit, IS_STRING, 1, "null")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_expirememberat, 0, 3, Redis, MAY_BE_LONG|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, field, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, timestamp, IS_LONG, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_Redis_incr arginfo_class_Redis_decr
#define arginfo_class_Redis_incrBy arginfo_class_Redis_decrBy
@@ -1270,6 +1283,8 @@ ZEND_METHOD(Redis, hSetNx);
ZEND_METHOD(Redis, hStrLen);
ZEND_METHOD(Redis, hVals);
ZEND_METHOD(Redis, hscan);
ZEND_METHOD(Redis, expiremember);
ZEND_METHOD(Redis, expirememberat);
ZEND_METHOD(Redis, incr);
ZEND_METHOD(Redis, incrBy);
ZEND_METHOD(Redis, incrByFloat);
@@ -1526,6 +1541,8 @@ static const zend_function_entry class_Redis_methods[] = {
ZEND_ME(Redis, hStrLen, arginfo_class_Redis_hStrLen, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hVals, arginfo_class_Redis_hVals, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hscan, arginfo_class_Redis_hscan, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, expiremember, arginfo_class_Redis_expiremember, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, expirememberat, arginfo_class_Redis_expirememberat, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, incr, arginfo_class_Redis_incr, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, incrBy, arginfo_class_Redis_incrBy, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, incrByFloat, arginfo_class_Redis_incrByFloat, ZEND_ACC_PUBLIC)
@@ -2027,12 +2044,16 @@ static zend_class_entry *register_class_Redis(void)
zend_string *const_OPT_BACKOFF_CAP_name = zend_string_init_interned("OPT_BACKOFF_CAP", sizeof("OPT_BACKOFF_CAP") - 1, 1);
zend_declare_class_constant_ex(class_entry, const_OPT_BACKOFF_CAP_name, &const_OPT_BACKOFF_CAP_value, ZEND_ACC_PUBLIC, NULL);
zend_string_release(const_OPT_BACKOFF_CAP_name);
#if (PHP_VERSION_ID >= 80200)
#if (PHP_VERSION_ID >= 80000)
zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "auth", sizeof("auth") - 1), 0, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0);
zend_string *attribute_name_SensitiveParameter_func_auth_arg0_0 = zend_string_init_interned("SensitiveParameter", sizeof("SensitiveParameter") - 1, 1);
zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "auth", sizeof("auth") - 1), 0, attribute_name_SensitiveParameter_func_auth_arg0_0, 0);
zend_string_release(attribute_name_SensitiveParameter_func_auth_arg0_0);
zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "migrate", sizeof("migrate") - 1), 7, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0);
zend_string *attribute_name_SensitiveParameter_func_migrate_arg7_0 = zend_string_init_interned("SensitiveParameter", sizeof("SensitiveParameter") - 1, 1);
zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "migrate", sizeof("migrate") - 1), 7, attribute_name_SensitiveParameter_func_migrate_arg7_0, 0);
zend_string_release(attribute_name_SensitiveParameter_func_migrate_arg7_0);
#endif
return class_entry;

View File

@@ -1303,6 +1303,14 @@ PHP_METHOD(RedisCluster, getbit) {
}
/* }}} */
PHP_METHOD(RedisCluster, expiremember) {
CLUSTER_PROCESS_CMD(expiremember, cluster_long_resp, 0);
}
PHP_METHOD(RedisCluster, expirememberat) {
CLUSTER_PROCESS_CMD(expiremember, cluster_long_resp, 0);
}
/* {{{ proto long RedisCluster::setbit(string key, long offset, bool onoff) */
PHP_METHOD(RedisCluster, setbit) {
CLUSTER_PROCESS_CMD(setbit, cluster_long_resp, 0);

View File

@@ -495,6 +495,16 @@ class RedisCluster {
*/
public function hscan(string $key, null|int|string &$iterator, ?string $pattern = null, int $count = 0): array|bool;
/**
* @see Redis::expiremember
*/
public function expiremember(string $key, string $field, int $ttl, ?string $unit = null): Redis|int|false;
/**
* @see Redis::expirememberat
*/
public function expirememberat(string $key, string $field, int $timestamp): Redis|int|false;
/**
* @see https://redis.io/commands/hrandfield
*/

View File

@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 5713c5b2f88ddead50088f14026447801120fa33 */
* Stub hash: b9310b607794caa862d509ba316a2a512d2736fe */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster___construct, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 1)
@@ -416,6 +416,19 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_RedisCluster_hscan, 0, 2,
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, count, IS_LONG, 0, "0")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_RedisCluster_expiremember, 0, 3, Redis, MAY_BE_LONG|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, field, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, ttl, IS_LONG, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, unit, IS_STRING, 1, "null")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_RedisCluster_expirememberat, 0, 3, Redis, MAY_BE_LONG|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, field, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, timestamp, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_RedisCluster_hrandfield, 0, 1, RedisCluster, MAY_BE_STRING|MAY_BE_ARRAY)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 1, "null")
@@ -1135,6 +1148,8 @@ ZEND_METHOD(RedisCluster, hlen);
ZEND_METHOD(RedisCluster, hmget);
ZEND_METHOD(RedisCluster, hmset);
ZEND_METHOD(RedisCluster, hscan);
ZEND_METHOD(RedisCluster, expiremember);
ZEND_METHOD(RedisCluster, expirememberat);
ZEND_METHOD(RedisCluster, hrandfield);
ZEND_METHOD(RedisCluster, hset);
ZEND_METHOD(RedisCluster, hsetnx);
@@ -1362,6 +1377,8 @@ static const zend_function_entry class_RedisCluster_methods[] = {
ZEND_ME(RedisCluster, hmget, arginfo_class_RedisCluster_hmget, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hmset, arginfo_class_RedisCluster_hmset, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hscan, arginfo_class_RedisCluster_hscan, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, expiremember, arginfo_class_RedisCluster_expiremember, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, expirememberat, arginfo_class_RedisCluster_expirememberat, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hrandfield, arginfo_class_RedisCluster_hrandfield, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hset, arginfo_class_RedisCluster_hset, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hsetnx, arginfo_class_RedisCluster_hsetnx, ZEND_ACC_PUBLIC)
@@ -1541,10 +1558,12 @@ static zend_class_entry *register_class_RedisCluster(void)
zend_string *const_FAILOVER_DISTRIBUTE_SLAVES_name = zend_string_init_interned("FAILOVER_DISTRIBUTE_SLAVES", sizeof("FAILOVER_DISTRIBUTE_SLAVES") - 1, 1);
zend_declare_class_constant_ex(class_entry, const_FAILOVER_DISTRIBUTE_SLAVES_name, &const_FAILOVER_DISTRIBUTE_SLAVES_value, ZEND_ACC_PUBLIC, NULL);
zend_string_release(const_FAILOVER_DISTRIBUTE_SLAVES_name);
#if (PHP_VERSION_ID >= 80200)
#if (PHP_VERSION_ID >= 80000)
zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "__construct", sizeof("__construct") - 1), 5, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0);
zend_string *attribute_name_SensitiveParameter_func___construct_arg5_0 = zend_string_init_interned("SensitiveParameter", sizeof("SensitiveParameter") - 1, 1);
zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "__construct", sizeof("__construct") - 1), 5, attribute_name_SensitiveParameter_func___construct_arg5_0, 0);
zend_string_release(attribute_name_SensitiveParameter_func___construct_arg5_0);
#endif
return class_entry;

View File

@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 5713c5b2f88ddead50088f14026447801120fa33 */
* Stub hash: b9310b607794caa862d509ba316a2a512d2736fe */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster___construct, 0, 0, 1)
ZEND_ARG_INFO(0, name)
@@ -368,6 +368,19 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_hscan, 0, 0, 2)
ZEND_ARG_INFO(0, count)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_expiremember, 0, 0, 3)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, field)
ZEND_ARG_INFO(0, ttl)
ZEND_ARG_INFO(0, unit)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_expirememberat, 0, 0, 3)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, field)
ZEND_ARG_INFO(0, timestamp)
ZEND_END_ARG_INFO()
#define arginfo_class_RedisCluster_hrandfield arginfo_class_RedisCluster_getex
#define arginfo_class_RedisCluster_hset arginfo_class_RedisCluster_hincrby
@@ -977,6 +990,8 @@ ZEND_METHOD(RedisCluster, hlen);
ZEND_METHOD(RedisCluster, hmget);
ZEND_METHOD(RedisCluster, hmset);
ZEND_METHOD(RedisCluster, hscan);
ZEND_METHOD(RedisCluster, expiremember);
ZEND_METHOD(RedisCluster, expirememberat);
ZEND_METHOD(RedisCluster, hrandfield);
ZEND_METHOD(RedisCluster, hset);
ZEND_METHOD(RedisCluster, hsetnx);
@@ -1204,6 +1219,8 @@ static const zend_function_entry class_RedisCluster_methods[] = {
ZEND_ME(RedisCluster, hmget, arginfo_class_RedisCluster_hmget, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hmset, arginfo_class_RedisCluster_hmset, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hscan, arginfo_class_RedisCluster_hscan, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, expiremember, arginfo_class_RedisCluster_expiremember, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, expirememberat, arginfo_class_RedisCluster_expirememberat, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hrandfield, arginfo_class_RedisCluster_hrandfield, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hset, arginfo_class_RedisCluster_hset, ZEND_ACC_PUBLIC)
ZEND_ME(RedisCluster, hsetnx, arginfo_class_RedisCluster_hsetnx, ZEND_ACC_PUBLIC)

View File

@@ -6079,6 +6079,57 @@ int redis_expire_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
return SUCCESS;
}
static int
generic_expiremember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char *kw, size_t kw_len, int has_unit, char **cmd,
int *cmd_len, short *slot)
{
zend_string *key, *mem, *unit = NULL;
smart_string cmdstr = {0};
zend_long expiry;
ZEND_PARSE_PARAMETERS_START(3, has_unit ? 4 : 3)
Z_PARAM_STR(key)
Z_PARAM_STR(mem)
Z_PARAM_LONG(expiry)
if (has_unit) {
Z_PARAM_OPTIONAL
Z_PARAM_STR_OR_NULL(unit)
}
ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
redis_cmd_init_sstr(&cmdstr, 3 + (unit != NULL), kw, kw_len);
redis_cmd_append_sstr_key_zstr(&cmdstr, key, redis_sock, slot);
redis_cmd_append_sstr_zstr(&cmdstr, mem);
redis_cmd_append_sstr_long(&cmdstr, expiry);
if (unit != NULL) {
redis_cmd_append_sstr_zstr(&cmdstr, unit);
}
*cmd = cmdstr.c;
*cmd_len = cmdstr.len;
return SUCCESS;
}
int redis_expiremember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char **cmd, int *cmd_len, short *slot, void **ctx)
{
return generic_expiremember_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU,
redis_sock, ZEND_STRL("EXPIREMEMBER"), 1,
cmd, cmd_len, slot);
}
int redis_expirememberat_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char **cmd, int *cmd_len, short *slot, void **ctx)
{
return generic_expiremember_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU,
redis_sock, ZEND_STRL("EXPIREMEMBERAT"), 0,
cmd, cmd_len, slot);
}
int
redis_sentinel_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx)

View File

@@ -350,6 +350,12 @@ int redis_xreadgroup_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
int redis_xtrim_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char **cmd, int *cmd_len, short *slot, void **ctx);
int redis_expiremember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char **cmd, int *cmd_len, short *slot, void **ctx);
int redis_expirememberat_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char **cmd, int *cmd_len, short *slot, void **ctx);
int redis_lmove_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
char *kw, char **cmd, int *cmd_len, short *slot, void **ctx);

View File

@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 1cc5fe0df8dfa7d95f2bc45c2383132a68629f24 */
* Stub hash: bacbe6b1d55da4ba6d370fff1090e8de0363c4c2 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
ZEND_ARG_INFO(0, options)
@@ -413,6 +413,19 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_hscan, 0, 0, 2)
ZEND_ARG_INFO(0, count)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_expiremember, 0, 0, 3)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, field)
ZEND_ARG_INFO(0, ttl)
ZEND_ARG_INFO(0, unit)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_expirememberat, 0, 0, 3)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, field)
ZEND_ARG_INFO(0, timestamp)
ZEND_END_ARG_INFO()
#define arginfo_class_Redis_incr arginfo_class_Redis_decr
#define arginfo_class_Redis_incrBy arginfo_class_Redis_append
@@ -1113,6 +1126,8 @@ ZEND_METHOD(Redis, hSetNx);
ZEND_METHOD(Redis, hStrLen);
ZEND_METHOD(Redis, hVals);
ZEND_METHOD(Redis, hscan);
ZEND_METHOD(Redis, expiremember);
ZEND_METHOD(Redis, expirememberat);
ZEND_METHOD(Redis, incr);
ZEND_METHOD(Redis, incrBy);
ZEND_METHOD(Redis, incrByFloat);
@@ -1369,6 +1384,8 @@ static const zend_function_entry class_Redis_methods[] = {
ZEND_ME(Redis, hStrLen, arginfo_class_Redis_hStrLen, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hVals, arginfo_class_Redis_hVals, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, hscan, arginfo_class_Redis_hscan, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, expiremember, arginfo_class_Redis_expiremember, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, expirememberat, arginfo_class_Redis_expirememberat, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, incr, arginfo_class_Redis_incr, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, incrBy, arginfo_class_Redis_incrBy, ZEND_ACC_PUBLIC)
ZEND_ME(Redis, incrByFloat, arginfo_class_Redis_incrByFloat, ZEND_ACC_PUBLIC)

View File

@@ -716,6 +716,22 @@ class Redis_Test extends TestSuite {
$this->redis->mget(array_keys($kvals)));
}
public function testExpireMember() {
if ( ! $this->is_keydb)
$this->markTestSkipped();
$this->redis->del('h');
$this->redis->hmset('h', ['f1' => 'v1', 'f2' => 'v2', 'f3' => 'v3', 'f4' => 'v4']);
$this->assertEquals(1, $this->redis->expiremember('h', 'f1', 1));
$this->assertEquals(1, $this->redis->expiremember('h', 'f2', 1000, 'ms'));
$this->assertEquals(1, $this->redis->expiremember('h', 'f3', 1000, null));
$this->assertEquals(0, $this->redis->expiremember('h', 'nk', 10));
$this->assertEquals(1, $this->redis->expirememberat('h', 'f4', time() + 1));
$this->assertEquals(0, $this->redis->expirememberat('h', 'nk', time() + 1));
}
public function testExpire() {
$this->redis->del('key');
$this->redis->set('key', 'value');