Skip to content

Commit

Permalink
feat: hashKey add ttl
Browse files Browse the repository at this point in the history
  • Loading branch information
chaz6chez committed Aug 20, 2024
1 parent e79d6b9 commit d7965da
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 36 deletions.
74 changes: 56 additions & 18 deletions src/Traits/HashMethods.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,22 @@ trait HashMethods
* @param string $key
* @param string|int $hashKey
* @param mixed $hashValue
* @param int $ttl
* @return bool
*/
protected static function _HSet(string $key, string|int $hashKey, mixed $hashValue): bool
protected static function _HSet(string $key, string|int $hashKey, mixed $hashValue, int $ttl = 0): bool
{
$func = __FUNCTION__;
$params = func_get_args();
self::_Atomic($key, function () use (
$key, $hashKey, $hashValue, $func, $params
$key, $hashKey, $hashValue, $ttl, $func, $params
) {
$hash = self::_Get($key, []);
$hash[$hashKey] = $hashValue;
$hash[$hashKey] = [
'_value' => $hashValue,
'_ttl' => $ttl,
'_timestamp' => time()
];
self::_Set($key, $hash);
return [
'timestamp' => microtime(true),
Expand All @@ -51,19 +56,29 @@ protected static function _HSet(string $key, string|int $hashKey, mixed $hashVal
* @param string $key
* @param string|int $hashKey
* @param int|float $hashValue
* @param int $ttl
* @return bool|int|float
*/
protected static function _HIncr(string $key, string|int $hashKey, int|float $hashValue = 1): bool|int|float
protected static function _HIncr(string $key, string|int $hashKey, int|float $hashValue = 1, int $ttl = 0): bool|int|float
{
$func = __FUNCTION__;
$result = false;
$params = func_get_args();
self::_Atomic($key, function () use (
$key, $hashKey, $hashValue, $func, $params, &$result
$key, $hashKey, $hashValue, $ttl, $func, $params, &$result
) {
$hash = self::_Get($key, []);
if (is_numeric($v = ($hash[$hashKey] ?? 0))) {
$hash[$hashKey] = $result = $v + $hashValue;
$value = $hash[$hashKey]['_value'] ?? 0;
$oldTtl = $hash[$hashKey]['_ttl'] ?? 0;
$timestamp = $hash[$hashKey]['_timestamp'] ?? 0;
if (is_numeric($value)) {
$now = time();
$value = ($oldTtl <= 0 or (($timestamp + $oldTtl) >= $now)) ? $value : 0;
$hash[$hashKey] = [
'_value' => $result = $value + $hashValue,
'_ttl' => ($ttl > 0) ? $ttl : ($timestamp > 0 ? $now - $timestamp : 0),
'_timestamp' => $now,
];
self::_Set($key, $hash);
}
return [
Expand All @@ -82,19 +97,29 @@ protected static function _HIncr(string $key, string|int $hashKey, int|float $ha
* @param string $key
* @param string|int $hashKey
* @param int|float $hashValue
* @param int $ttl
* @return bool|int|float
*/
protected static function _HDecr(string $key, string|int $hashKey, int|float $hashValue = 1): bool|int|float
protected static function _HDecr(string $key, string|int $hashKey, int|float $hashValue = 1, int $ttl = 0): bool|int|float
{
$func = __FUNCTION__;
$result = false;
$params = func_get_args();
self::_Atomic($key, function () use (
$key, $hashKey, $hashValue, $func, $params, &$result
$key, $hashKey, $hashValue, $ttl, $func, $params, &$result
) {
$hash = self::_Get($key, []);
if (is_numeric($v = ($hash[$hashKey] ?? 0))) {
$hash[$hashKey] = $result = $v - $hashValue;
$value = $hash[$hashKey]['_value'] ?? 0;
$oldTtl = $hash[$hashKey]['_ttl'] ?? 0;
$timestamp = $hash[$hashKey]['_timestamp'] ?? 0;
if (is_numeric($value)) {
$now = time();
$value = ($oldTtl <= 0 or (($timestamp + $oldTtl) >= $now)) ? $value : 0;
$hash[$hashKey] = [
'_value' => $result = $value - $hashValue,
'_ttl' => ($ttl > 0) ? $ttl : ($timestamp > 0 ? $now - $timestamp : 0),
'_timestamp' => $now,
];
self::_Set($key, $hash);
}
return [
Expand Down Expand Up @@ -148,8 +173,12 @@ protected static function _HDel(string $key, string|int ...$hashKey): bool
*/
protected static function _HGet(string $key, string|int $hashKey, mixed $default = null): mixed
{
$now = time();
$hash = self::_Get($key, []);
return $hash[$hashKey] ?? $default;
$value = $hash[$hashKey]['_value'] ?? $default;
$ttl = $hash[$hashKey]['_ttl'] ?? 0;
$timestamp = $hash[$hashKey]['_timestamp'] ?? 0;
return ($ttl <= 0 or (($timestamp + $ttl) >= $now)) ? $value : $default;
}

/**
Expand All @@ -163,8 +192,11 @@ protected static function _HExists(string $key, string|int ...$hashKey): array
{
$hash = self::_Get($key, []);
$result = [];
$now = time();
foreach ($hashKey as $hk) {
if (isset($hash[$hk])) {
$ttl = $hash[$hk]['_ttl'] ?? 0;
$timestamp = $hash[$hk]['_timestamp'] ?? 0;
if (($ttl <= 0 or (($timestamp + $ttl) >= $now)) and isset($hash[$hk]['_value'])) {
$result[$hk] = true;
}
}
Expand All @@ -181,11 +213,17 @@ protected static function _HExists(string $key, string|int ...$hashKey): array
protected static function _HKeys(string $key, null|string $regex = null): array
{
$hash = self::_Get($key, []);
$keys = array_keys($hash);
if ($regex !== null) {
$keys = array_values(array_filter($keys, function($key) use ($regex) {
return preg_match($regex, $key);
}));
$keys = [];
$now = time();
foreach ($hash as $hashKey => $hashValue) {
$ttl = $hashValue['_ttl'] ?? 0;
$timestamp = $hashValue['_timestamp'] ?? 0;
if (($ttl <= 0 or (($timestamp + $ttl) >= $now)) and isset($hashValue['_value'])) {
if ($regex !== null and preg_match($regex, $key)) {
continue;
}
$keys[] = $hashKey;
}
}
return $keys;
}
Expand Down
104 changes: 86 additions & 18 deletions tests/HashTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ public function testHashGet(): void
// 单进程执行
$this->assertEquals(null, Cache::HGet($key, $hash));
apcu_add($key, [
$hash => $hash
$hash => [
'_value' => $hash,
'_ttl' => 0,
'_timestamp' => time()
]
]);
$this->assertEquals([], Cache::LockInfo());
$this->assertEquals($hash, Cache::HGet($key, $hash));
Expand All @@ -24,7 +28,11 @@ public function testHashGet(): void
$this->assertEquals(null, Cache::HGet($key, $hash));
$this->childExec(static function (string $key, string $hash) {
apcu_add($key, [
$hash => $hash
$hash => [
'_value' => $hash,
'_ttl' => 0,
'_timestamp' => time()
]
]);
}, $key, $hash);
$this->assertEquals([], Cache::LockInfo());
Expand All @@ -42,7 +50,11 @@ public function testHashSet(): void
$this->assertTrue(Cache::HSet($key, $hash, $hash));
$this->assertEquals([], Cache::LockInfo());
$this->assertEquals([
$hash => $hash
$hash => [
'_value' => $hash,
'_ttl' => 0,
'_timestamp' => time()
]
], apcu_fetch($key));
// 清理
apcu_delete($key);
Expand All @@ -54,7 +66,11 @@ public function testHashSet(): void
}, $key, $hash);
$this->assertEquals([], Cache::LockInfo());
$this->assertEquals([
$hash => $hash
$hash => [
'_value' => $hash,
'_ttl' => 0,
'_timestamp' => time()
]
], apcu_fetch($key));
// 清理
apcu_delete($key);
Expand Down Expand Up @@ -98,8 +114,12 @@ public function testHashExists(): void

$this->assertEquals([], Cache::HExists($key, 'a'));
apcu_add($key, [
'a' => 1,
'b' => 2
'a' => [
'_value' => 1
],
'b' => [
'_value' => 2
]
]);
$this->assertEquals([
'a' => true, 'b' => true
Expand All @@ -116,15 +136,27 @@ public function testHashIncr(): void
$this->assertFalse(apcu_fetch($key));
$this->assertEquals(1, Cache::HIncr($key, 'a'));
$this->assertEquals([
'a' => 1
'a' => [
'_value' => 1,
'_ttl' => 0,
'_timestamp' => time()
]
], apcu_fetch($key));
$this->assertEquals(3, Cache::HIncr($key, 'a', 2));
$this->assertEquals([
'a' => 3
'a' => [
'_value' => 3,
'_ttl' => 0,
'_timestamp' => time()
]
], apcu_fetch($key));
$this->assertEquals(4.1, Cache::HIncr($key, 'a', 1.1));
$this->assertEquals([
'a' => 4.1
'a' => [
'_value' => 4.1,
'_ttl' => 0,
'_timestamp' => time()
]
], apcu_fetch($key));
// 清理
apcu_delete($key);
Expand All @@ -135,19 +167,31 @@ public function testHashIncr(): void
Cache::HIncr($key, 'a');
}, $key);
$this->assertEquals([
'a' => 1
'a' => [
'_value' => 1,
'_ttl' => 0,
'_timestamp' => time()
]
], apcu_fetch($key));
$this->childExec(static function (string $key) {
Cache::HIncr($key, 'a',2);
}, $key);
$this->assertEquals([
'a' => 3
'a' => [
'_value' => 3,
'_ttl' => 0,
'_timestamp' => time()
]
], apcu_fetch($key));
$this->childExec(static function (string $key) {
Cache::HIncr($key, 'a',1.1);
}, $key);
$this->assertEquals([
'a' => 4.1
'a' => [
'_value' => 4.1,
'_ttl' => 0,
'_timestamp' => time()
]
], apcu_fetch($key));
// 清理
apcu_delete($key);
Expand All @@ -160,15 +204,27 @@ public function testHashDecr(): void
$this->assertFalse(apcu_fetch($key));
$this->assertEquals(-1, Cache::HDecr($key, 'a'));
$this->assertEquals([
'a' => -1
'a' => [
'_value' => -1,
'_ttl' => 0,
'_timestamp' => time()
]
], apcu_fetch($key));
$this->assertEquals(-3, Cache::HDecr($key, 'a', 2));
$this->assertEquals([
'a' => -3
'a' => [
'_value' => -3,
'_ttl' => 0,
'_timestamp' => time()
]
], apcu_fetch($key));
$this->assertEquals(-4.1, Cache::HDecr($key, 'a', 1.1));
$this->assertEquals([
'a' => -4.1
'a' => [
'_value' => -4.1,
'_ttl' => 0,
'_timestamp' => time()
]
], apcu_fetch($key));
// 清理
apcu_delete($key);
Expand All @@ -179,19 +235,31 @@ public function testHashDecr(): void
Cache::HDecr($key, 'a');
}, $key);
$this->assertEquals([
'a' => -1
'a' => [
'_value' => -1,
'_ttl' => 0,
'_timestamp' => time()
]
], apcu_fetch($key));
$this->childExec(static function (string $key) {
Cache::HDecr($key, 'a', 2);
}, $key);
$this->assertEquals([
'a' => -3
'a' => [
'_value' => -3,
'_ttl' => 0,
'_timestamp' => time()
]
], apcu_fetch($key));
$this->childExec(static function (string $key) {
Cache::HDecr($key, 'a', 1.1);
}, $key);
$this->assertEquals([
'a' => -4.1
'a' => [
'_value' => -4.1,
'_ttl' => 0,
'_timestamp' => time()
]
], apcu_fetch($key));
// 清理
apcu_delete($key);
Expand Down

0 comments on commit d7965da

Please sign in to comment.