mirror of
https://gitee.com/hyperf/hyperf.git
synced 2024-12-02 03:37:44 +08:00
Fixed bug that RedisSecondMetaGenerator
will generate the same meta. (#2640)
* Fixed bug that `RedisSecondMetaGenerator` will generate the same meta. * Update RedisMetaGenerator.php * Update CHANGELOG-2.0.md
This commit is contained in:
parent
044d827d2a
commit
84e19f78de
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
- [#2634](https://github.com/hyperf/hyperf/pull/2634) Fixed bug that `RedisSecondMetaGenerator` will generate the same meta.
|
- [#2634](https://github.com/hyperf/hyperf/pull/2634) [#2640](https://github.com/hyperf/hyperf/pull/2640) Fixed bug that `RedisSecondMetaGenerator` will generate the same meta.
|
||||||
- [#2639](https://github.com/hyperf/hyperf/pull/2639) Fixed exception will not be normalized for json-rpc.
|
- [#2639](https://github.com/hyperf/hyperf/pull/2639) Fixed exception will not be normalized for json-rpc.
|
||||||
|
|
||||||
# v2.0.14 - 2020-10-12
|
# v2.0.14 - 2020-10-12
|
||||||
|
@ -2,9 +2,12 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
$code = 0;
|
$code = 0;
|
||||||
Swoole\Coroutine::set(['exit_condition' => function(){
|
Swoole\Coroutine::set([
|
||||||
return Swoole\Coroutine::stats()['coroutine_num'] === 0;
|
'hook_flags' => SWOOLE_HOOK_ALL,
|
||||||
}]);
|
'exit_condition' => function(){
|
||||||
|
return Swoole\Coroutine::stats()['coroutine_num'] === 0;
|
||||||
|
}
|
||||||
|
]);
|
||||||
Swoole\Coroutine\Run(function () use (&$code) {
|
Swoole\Coroutine\Run(function () use (&$code) {
|
||||||
if (version_compare('7.1.0', PHP_VERSION, '>')) {
|
if (version_compare('7.1.0', PHP_VERSION, '>')) {
|
||||||
fwrite(
|
fwrite(
|
||||||
|
@ -42,14 +42,14 @@ abstract class MetaGenerator implements MetaGeneratorInterface
|
|||||||
if ($this->sequence == 0) {
|
if ($this->sequence == 0) {
|
||||||
$timestamp = $this->getNextTimestamp();
|
$timestamp = $this->getNextTimestamp();
|
||||||
}
|
}
|
||||||
|
} elseif ($timestamp < $this->lastTimestamp) {
|
||||||
|
$this->clockMovedBackwards($timestamp, $this->lastTimestamp);
|
||||||
|
$this->sequence = ($this->sequence + 1) % $this->configuration->maxSequence();
|
||||||
|
$timestamp = $this->lastTimestamp;
|
||||||
} else {
|
} else {
|
||||||
$this->sequence = 0;
|
$this->sequence = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($timestamp < $this->lastTimestamp) {
|
|
||||||
$this->clockMovedBackwards($timestamp, $this->lastTimestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($timestamp < $this->beginTimestamp) {
|
if ($timestamp < $this->beginTimestamp) {
|
||||||
throw new SnowflakeException(sprintf('The beginTimestamp %d is invalid, because it smaller than timestamp %d.', $this->beginTimestamp, $timestamp));
|
throw new SnowflakeException(sprintf('The beginTimestamp %d is invalid, because it smaller than timestamp %d.', $this->beginTimestamp, $timestamp));
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,11 @@ class RedisSecondMetaGenerator extends RedisMetaGenerator
|
|||||||
|
|
||||||
public function getNextTimestamp(): int
|
public function getNextTimestamp(): int
|
||||||
{
|
{
|
||||||
$timestamp = $this->getTimestamp();
|
return $this->lastTimestamp + 1;
|
||||||
while ($timestamp <= $this->lastTimestamp) {
|
}
|
||||||
usleep(1000);
|
|
||||||
$timestamp = $this->getTimestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $timestamp;
|
protected function clockMovedBackwards($timestamp, $lastTimestamp)
|
||||||
|
{
|
||||||
|
// Don't throw exception
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ class RedisMetaGeneratorTest extends TestCase
|
|||||||
$this->assertSame($meta->getWorkerId(), $userId % 31);
|
$this->assertSame($meta->getWorkerId(), $userId % 31);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetNextTimestamp()
|
public function testRedisSecondNextTimestamp()
|
||||||
{
|
{
|
||||||
$container = $this->getContainer();
|
$container = $this->getContainer();
|
||||||
$hConfig = $container->get(ConfigInterface::class);
|
$hConfig = $container->get(ConfigInterface::class);
|
||||||
@ -147,7 +147,43 @@ class RedisMetaGeneratorTest extends TestCase
|
|||||||
$time = $metaGenerator->getTimestamp();
|
$time = $metaGenerator->getTimestamp();
|
||||||
$nextTime = $metaGenerator->getNextTimestamp();
|
$nextTime = $metaGenerator->getNextTimestamp();
|
||||||
$this->assertSame($time + 1, $nextTime);
|
$this->assertSame($time + 1, $nextTime);
|
||||||
$this->assertSame(time(), $nextTime);
|
}
|
||||||
|
|
||||||
|
public function testGenerateSameMetaForRedisSecond()
|
||||||
|
{
|
||||||
|
$container = $this->getContainer();
|
||||||
|
$hConfig = $container->get(ConfigInterface::class);
|
||||||
|
$config = new SnowflakeConfig();
|
||||||
|
$metaGenerator = new RedisSecondMetaGenerator($config, MetaGeneratorInterface::DEFAULT_BEGIN_SECOND, $hConfig);
|
||||||
|
$generator = new SnowflakeIdGenerator($metaGenerator);
|
||||||
|
$result = [];
|
||||||
|
$channel = new Channel(2);
|
||||||
|
go(function () use (&$result, $generator, $channel) {
|
||||||
|
try {
|
||||||
|
for ($i = 0; $i < 4100; ++$i) {
|
||||||
|
$result[] = $generator->generate();
|
||||||
|
}
|
||||||
|
} catch (\Throwable $exception) {
|
||||||
|
} finally {
|
||||||
|
$channel->push(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
go(function () use (&$result, $generator, $channel) {
|
||||||
|
try {
|
||||||
|
for ($i = 0; $i < 900; ++$i) {
|
||||||
|
$result[] = $generator->generate();
|
||||||
|
}
|
||||||
|
} catch (\Throwable $exception) {
|
||||||
|
} finally {
|
||||||
|
$channel->push(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$channel->pop(5);
|
||||||
|
$channel->pop(5);
|
||||||
|
|
||||||
|
$this->assertSame(5000, count(array_unique($result)));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getContainer()
|
protected function getContainer()
|
||||||
@ -184,6 +220,8 @@ class RedisMetaGeneratorTest extends TestCase
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$container = Mockery::mock(Container::class);
|
$container = Mockery::mock(Container::class);
|
||||||
|
ApplicationContext::setContainer($container);
|
||||||
|
|
||||||
$container->shouldReceive('get')->with(ConfigInterface::class)->andReturn($config);
|
$container->shouldReceive('get')->with(ConfigInterface::class)->andReturn($config);
|
||||||
$container->shouldReceive('make')->with(Channel::class, Mockery::any())->andReturnUsing(function ($class, $args) {
|
$container->shouldReceive('make')->with(Channel::class, Mockery::any())->andReturnUsing(function ($class, $args) {
|
||||||
return new Channel($args['size']);
|
return new Channel($args['size']);
|
||||||
@ -200,7 +238,6 @@ class RedisMetaGeneratorTest extends TestCase
|
|||||||
return new RedisProxy($factory, $args['pool']);
|
return new RedisProxy($factory, $args['pool']);
|
||||||
});
|
});
|
||||||
|
|
||||||
ApplicationContext::setContainer($container);
|
|
||||||
return $container;
|
return $container;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user