mirror of
https://gitee.com/hyperf/hyperf.git
synced 2024-11-29 18:27:44 +08:00
Fixed bug that increment/decrement
does not works as expect when used in transaction. (#3598)
This commit is contained in:
parent
6f66dbcffd
commit
6d97e438c2
@ -1,5 +1,9 @@
|
||||
# v2.1.18 - TBD
|
||||
|
||||
## Fixed
|
||||
|
||||
- [#3598](https://github.com/hyperf/hyperf/pull/3598) Fixed bug that `increment/decrement` does not works as expect when used in transaction for model-cache.
|
||||
|
||||
# v2.1.17 - 2021-05-17
|
||||
|
||||
## Fixed
|
||||
|
@ -78,7 +78,9 @@ trait Cacheable
|
||||
{
|
||||
$res = parent::increment($column, $amount, $extra);
|
||||
if ($res > 0) {
|
||||
if (empty($extra)) {
|
||||
if ($this->getConnection()->transactionLevel() && $this instanceof CacheableInterface) {
|
||||
InvalidCacheManager::instance()->push($this);
|
||||
} elseif (empty($extra)) {
|
||||
// Only increment a column's value.
|
||||
/** @var Manager $manager */
|
||||
$manager = $this->getContainer()->get(Manager::class);
|
||||
@ -101,7 +103,9 @@ trait Cacheable
|
||||
{
|
||||
$res = parent::decrement($column, $amount, $extra);
|
||||
if ($res > 0) {
|
||||
if (empty($extra)) {
|
||||
if ($this->getConnection()->transactionLevel() && $this instanceof CacheableInterface) {
|
||||
InvalidCacheManager::instance()->push($this);
|
||||
} elseif (empty($extra)) {
|
||||
// Only decrement a column's value.
|
||||
/** @var Manager $manager */
|
||||
$manager = $this->getContainer()->get(Manager::class);
|
||||
|
@ -12,10 +12,13 @@ declare(strict_types=1);
|
||||
namespace HyperfTest\ModelCache;
|
||||
|
||||
use Hyperf\Database\Model\Relations\Relation;
|
||||
use Hyperf\DbConnection\Db;
|
||||
use Hyperf\DbConnection\Listener\InitTableCollectorListener;
|
||||
use Hyperf\ModelCache\EagerLoad\EagerLoader;
|
||||
use Hyperf\ModelCache\InvalidCacheManager;
|
||||
use Hyperf\ModelCache\Listener\EagerLoadListener;
|
||||
use Hyperf\Redis\RedisProxy;
|
||||
use Hyperf\Utils\Reflection\ClassInvoker;
|
||||
use HyperfTest\ModelCache\Stub\BookModel;
|
||||
use HyperfTest\ModelCache\Stub\ContainerStub;
|
||||
use HyperfTest\ModelCache\Stub\ImageModel;
|
||||
@ -381,4 +384,104 @@ class ModelCacheTest extends TestCase
|
||||
BookModel::findFromCache(1);
|
||||
$this->assertSame(100, $redis->ttl('{mc:default:m:book}:id:1'));
|
||||
}
|
||||
|
||||
public function testModelSaveInTransaction()
|
||||
{
|
||||
$container = ContainerStub::mockContainer();
|
||||
|
||||
$id = 209;
|
||||
UserModel::query()->firstOrCreate(['id' => $id], [
|
||||
'name' => uniqid(),
|
||||
'gender' => 1,
|
||||
]);
|
||||
|
||||
$redis = $container->make(RedisProxy::class, ['pool' => 'default']);
|
||||
|
||||
wait(function () use ($redis, $id) {
|
||||
Db::beginTransaction();
|
||||
try {
|
||||
$model = UserModel::findFromCache($id);
|
||||
/* @var \Redis $redis */
|
||||
$this->assertEquals(1, $redis->exists('{mc:default:m:user}:id:' . $id));
|
||||
$model->gender = 2;
|
||||
$model->save();
|
||||
$this->assertEquals(1, $redis->hGet('{mc:default:m:user}:id:' . $id, 'gender'));
|
||||
$invoker = new ClassInvoker(InvalidCacheManager::instance());
|
||||
$this->assertSame(1, count($invoker->models));
|
||||
Db::commit();
|
||||
} catch (\Throwable $exception) {
|
||||
Db::rollBack();
|
||||
}
|
||||
});
|
||||
|
||||
$this->assertSame(0, $redis->exists('{mc:default:m:user}:id:' . $id));
|
||||
|
||||
UserModel::query(true)->where('id', $id)->delete();
|
||||
}
|
||||
|
||||
public function testModelIncrInTransaction()
|
||||
{
|
||||
$container = ContainerStub::mockContainer();
|
||||
|
||||
$id = 209;
|
||||
UserModel::query()->firstOrCreate(['id' => $id], [
|
||||
'name' => uniqid(),
|
||||
'gender' => 1,
|
||||
]);
|
||||
|
||||
$redis = $container->make(RedisProxy::class, ['pool' => 'default']);
|
||||
|
||||
wait(function () use ($redis, $id) {
|
||||
Db::beginTransaction();
|
||||
try {
|
||||
$model = UserModel::findFromCache($id);
|
||||
/* @var \Redis $redis */
|
||||
$this->assertEquals(1, $redis->exists('{mc:default:m:user}:id:' . $id));
|
||||
$model->increment('gender');
|
||||
$this->assertEquals(1, $redis->hGet('{mc:default:m:user}:id:' . $id, 'gender'));
|
||||
$invoker = new ClassInvoker(InvalidCacheManager::instance());
|
||||
$this->assertSame(1, count($invoker->models));
|
||||
Db::commit();
|
||||
} catch (\Throwable $exception) {
|
||||
Db::rollBack();
|
||||
}
|
||||
});
|
||||
|
||||
$this->assertSame(0, $redis->exists('{mc:default:m:user}:id:' . $id));
|
||||
|
||||
UserModel::query(true)->where('id', $id)->delete();
|
||||
}
|
||||
|
||||
public function testModelDecrInTransaction()
|
||||
{
|
||||
$container = ContainerStub::mockContainer();
|
||||
|
||||
$id = 209;
|
||||
UserModel::query()->firstOrCreate(['id' => $id], [
|
||||
'name' => uniqid(),
|
||||
'gender' => 1,
|
||||
]);
|
||||
|
||||
$redis = $container->make(RedisProxy::class, ['pool' => 'default']);
|
||||
|
||||
wait(function () use ($redis, $id) {
|
||||
Db::beginTransaction();
|
||||
try {
|
||||
$model = UserModel::findFromCache($id);
|
||||
/* @var \Redis $redis */
|
||||
$this->assertEquals(1, $redis->exists('{mc:default:m:user}:id:' . $id));
|
||||
$model->decrement('gender');
|
||||
$this->assertEquals(1, $redis->hGet('{mc:default:m:user}:id:' . $id, 'gender'));
|
||||
$invoker = new ClassInvoker(InvalidCacheManager::instance());
|
||||
$this->assertSame(1, count($invoker->models));
|
||||
Db::commit();
|
||||
} catch (\Throwable $exception) {
|
||||
Db::rollBack();
|
||||
}
|
||||
});
|
||||
|
||||
$this->assertSame(0, $redis->exists('{mc:default:m:user}:id:' . $id));
|
||||
|
||||
UserModel::query(true)->where('id', $id)->delete();
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ use Hyperf\Database\Model\Events\Deleted;
|
||||
use Hyperf\Database\Model\Events\Saved;
|
||||
use Hyperf\DbConnection\Collector\TableCollector;
|
||||
use Hyperf\DbConnection\ConnectionResolver;
|
||||
use Hyperf\DbConnection\Db;
|
||||
use Hyperf\DbConnection\Frequency;
|
||||
use Hyperf\DbConnection\Pool\DbPool;
|
||||
use Hyperf\DbConnection\Pool\PoolFactory;
|
||||
@ -42,6 +43,7 @@ use Hyperf\Redis\Pool\RedisPool;
|
||||
use Hyperf\Redis\RedisProxy;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
use Hyperf\Utils\Packer\PhpSerializerPacker;
|
||||
use Hyperf\Utils\Waiter;
|
||||
use Mockery;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
@ -168,6 +170,8 @@ class ContainerStub
|
||||
$container->shouldReceive('get')->with(Manager::class)->andReturn(new Manager($container));
|
||||
$container->shouldReceive('get')->with(PhpSerializerPacker::class)->andReturn(new PhpSerializerPacker());
|
||||
$container->shouldReceive('get')->with(EagerLoader::class)->andReturn(new EagerLoader());
|
||||
$container->shouldReceive('get')->with(Waiter::class)->andReturn(new Waiter());
|
||||
$container->shouldReceive('get')->with(Db::class)->andReturn(new Db($container));
|
||||
return $container;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user