Skip to content

Commit b8dfbc3

Browse files
godruoyiBilge
andauthored
feat: support predis (#72)
* feat: support predis * add test for bulk generate id with predis resolver * Update composer.json Co-authored-by: Bilge <[email protected]> * add new phpcsfix rule "heredoc_indentation" * chore: rename PHPREDIS -> Predis * chore: remove predis from composer * chore: update readme * chore: fix test * fix unit test ensure all cache are overdue --------- Co-authored-by: Bilge <[email protected]>
1 parent 79d099d commit b8dfbc3

13 files changed

+219
-32
lines changed

.github/workflows/codestyle.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ jobs:
3939
- name: Install Laravel Illuminate Contracts
4040
run: composer require "illuminate/contracts"
4141

42+
- name: Install Predis Package
43+
run: composer require "predis/predis:^2.0"
44+
4245
- name: Code Style
4346
run: vendor/bin/pint --test --config ./pint.json
4447

.github/workflows/static-analysis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,8 @@ jobs:
3838
max_attempts: 3
3939
command: composer update --prefer-stable --prefer-dist --no-interaction --no-progress
4040

41+
- name: Install Predis Package
42+
run: composer require "predis/predis:^2.0"
43+
4144
- name: Execute type checking
4245
run: vendor/bin/phpstan

.github/workflows/test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ jobs:
4040
- name: Install Laravel Illuminate Contracts
4141
run: composer require "illuminate/contracts"
4242

43+
- name: Install Predis Package
44+
run: composer require "predis/predis:^2.0"
45+
4346
- name: PHPUnit Test
4447
run: vendor/bin/phpunit --display-incomplete --display-skipped --display-deprecations --display-errors --display-notices --display-warnings
4548
env:

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,23 @@ Based on this, we created this package and integrated multiple sequence-number p
4646
* RandomSequenceResolver (Random)
4747
* FileLockResolver(PHP file lock `fopen/flock`, **Concurrency Safety**
4848
* RedisSequenceResolver (based on redis psetex and incrby, **Concurrency Safety**)
49-
* LaravelSequenceResolver (based on redis psetex and incrby)
49+
* LaravelSequenceResolver (based on Laravel Cache [add](https://github.com/laravel/framework/blob/11.x/src/Illuminate/Contracts/Cache/Repository.php#L39) lock)
5050
* SwooleSequenceResolver (based on swoole_lock)
51+
* PredisSequenceResolver (based on redis psetex and incrby, **Concurrency Safety**)
5152

5253
Each provider only needs to ensure that the serial number generated in the same millisecond is different. You can get a unique ID.
5354

55+
56+
> [!NOTE]
57+
> If you want to use RedisSequenceResolver, please install the [redis](https://pecl.php.net/package/redis) extension:
58+
> pecl install redis
59+
>
60+
> If you want to use SwooleSequenceResolver, please install the swoole extension:
61+
> pecl install swoole
62+
>
63+
> If you want to use PredisSequenceResolver, please install the [predis/predis](https://github.com/predis/predis) package:
64+
> composer install predis/predis
65+
5466
> **Warning**
5567
> The RandomSequenceResolver does not guarantee that the generated IDs are unique, If you want to generate a unique ID, please use another resolver instead.
5668

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
},
3939
"scripts": {
4040
"test": "vendor/bin/phpunit",
41-
"pint": "vendor/bin/pint"
41+
"pint": "vendor/bin/pint --config pint.json"
4242
},
4343
"config": {
4444
"allow-plugins": {

pint.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
"php_unit_method_casing": {
88
"case": "snake_case"
99
},
10-
"no_superfluous_phpdoc_tags": false
10+
"no_superfluous_phpdoc_tags": false,
11+
"heredoc_indentation": {
12+
"indentation": "start_plus_one"
13+
}
1114
}
1215
}

src/FileLockResolver.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ protected function unlock($f): void
114114
/**
115115
* @param array<int, int> $contents
116116
* @param resource $f
117-
* @return bool
118117
*/
119118
public function updateContents(array $contents, $f): bool
120119
{

src/PredisSequenceResolver.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the godruoyi/php-snowflake.
7+
*
8+
* (c) Godruoyi <[email protected]>
9+
*
10+
* This source file is subject to the MIT license that is bundled.
11+
*/
12+
13+
namespace Godruoyi\Snowflake;
14+
15+
use Predis\Client as PredisClient;
16+
17+
class PredisSequenceResolver implements SequenceResolver
18+
{
19+
/**
20+
* The cache prefix.
21+
*/
22+
protected string $prefix = '';
23+
24+
/**
25+
* The default redis lua script
26+
*/
27+
protected static string $script = <<<'LUA'
28+
if redis.call('set', KEYS[1], ARGV[1], "EX", ARGV[2], "NX") then
29+
return 0
30+
else
31+
return redis.call('incr', KEYS[1])
32+
end
33+
LUA;
34+
35+
public function __construct(protected PredisClient $predisClient)
36+
{
37+
}
38+
39+
public function sequence(int $currentTime): int
40+
{
41+
return $this->predisClient->eval(self::$script, 1, $this->prefix.$currentTime, '0', '10') | 0;
42+
}
43+
44+
/**
45+
* Set cache prefix.
46+
*/
47+
public function setCachePrefix(string $prefix): self
48+
{
49+
$this->prefix = $prefix;
50+
51+
return $this;
52+
}
53+
}

src/RedisSequenceResolver.php

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ class RedisSequenceResolver implements SequenceResolver
2222
*/
2323
protected string $prefix = '';
2424

25+
/**
26+
* The default redis lua script
27+
*/
28+
protected static string $script = <<<'LUA'
29+
if redis.call('set', KEYS[1], ARGV[1], "EX", ARGV[2], "NX") then
30+
return 0
31+
else
32+
return redis.call('incr', KEYS[1])
33+
end
34+
LUA;
35+
2536
/**
2637
* Init resolve instance, must be connected.
2738
*
@@ -39,16 +50,8 @@ public function __construct(protected Redis $redis)
3950
*/
4051
public function sequence(int $currentTime): int
4152
{
42-
$lua = <<<'LUA'
43-
if redis.call('set', KEYS[1], ARGV[1], "EX", ARGV[2], "NX") then
44-
return 0
45-
else
46-
return redis.call('incr', KEYS[1])
47-
end
48-
LUA;
49-
5053
// 10 seconds
51-
return $this->redis->eval($lua, [$this->prefix.$currentTime, '0', '10'], 1) | 0;
54+
return $this->redis->eval(self::$script, [$this->prefix.$currentTime, '0', '10'], 1) | 0;
5255
}
5356

5457
/**

src/Snowflake.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ class Snowflake
3838

3939
/**
4040
* The Sequence Resolver instance.
41-
*
42-
* @var Closure|SequenceResolver|null
4341
*/
4442
protected SequenceResolver|null|Closure $sequence = null;
4543

0 commit comments

Comments
 (0)