LockTest.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. <?php
  2. /**
  3. * @author gaobinzhan <gaobinzhan@gmail.com>
  4. */
  5. namespace EasySwoole\ORM\Tests;
  6. use EasySwoole\ORM\Db\Config;
  7. use EasySwoole\ORM\Db\Connection;
  8. use EasySwoole\ORM\DbManager;
  9. use EasySwoole\ORM\Exception\Exception;
  10. use EasySwoole\ORM\Tests\models\TestA;
  11. use PHPUnit\Framework\TestCase;
  12. class LockTest extends TestCase
  13. {
  14. protected function setUp(): void
  15. {
  16. parent::setUp(); // TODO: Change the autogenerated stub
  17. $config = new Config(MYSQL_CONFIG);
  18. $config->setReturnCollection(true);
  19. $connection = new Connection($config);
  20. DbManager::getInstance()->addConnection($connection, 'a');
  21. $config = new Config(MYSQL_CONFIG);
  22. $config->setTimeout(2);
  23. $config->setReturnCollection(true);
  24. $connection = new Connection($config);
  25. DbManager::getInstance()->addConnection($connection, 'b');
  26. }
  27. private function add(): int
  28. {
  29. $model = new TestA();
  30. return $model->connection('a')->data(['a_name' => 1])->save();
  31. }
  32. public function testLockForUpdate()
  33. {
  34. $id = $this->add();
  35. $wg = new \Swoole\Coroutine\WaitGroup();
  36. $wg->add();
  37. go(function () use ($id, $wg) {
  38. // a连接处于事务 使用排他锁
  39. DbManager::getInstance()->startTransaction('a');
  40. TestA::create()->connection('a')->lockForUpdate()->get($id);
  41. \Co::sleep(3);
  42. DbManager::getInstance()->commit('a');
  43. $wg->done();
  44. });
  45. $wg->add();
  46. go(function () use ($id, &$result, $wg) {
  47. try {
  48. // 该数据加了锁 其它连接不可操作更新进入阻塞(任何锁不可加) b连接超时为2s 直接抛出异常
  49. TestA::create()->connection('b')->where(['id' => $id])->update(['a_name' => time()]);
  50. } catch (\Throwable $throwable) {
  51. $result = $throwable;
  52. } finally {
  53. $wg->done();
  54. }
  55. });
  56. $wg->wait(-1);
  57. $this->assertInstanceOf(Exception::class, $result);
  58. $this->delete();
  59. }
  60. public function testSharedLock()
  61. {
  62. $id = $this->add();
  63. $wg = new \Swoole\Coroutine\WaitGroup();
  64. $wg->add();
  65. go(function () use ($id, $wg) {
  66. // a连接处于事务 使用共享锁
  67. DbManager::getInstance()->startTransaction('a');
  68. TestA::create()->connection('a')->sharedLock()->get($id);
  69. \Co::sleep(3);
  70. DbManager::getInstance()->commit('a');
  71. $wg->done();
  72. });
  73. $wg->add();
  74. go(function () use ($id, &$result, $wg, &$data) {
  75. try {
  76. $data = TestA::create()->connection('a')->sharedLock()->get($id);
  77. // 该数据加了锁 其它连接不可操作更新进入阻塞(可加共享锁) b连接超时为2s 直接抛出异常
  78. TestA::create()->connection('b')->where(['id' => $id])->update(['a_name' => time()]);
  79. } catch (\Throwable $throwable) {
  80. $result = $throwable;
  81. } finally {
  82. $wg->done();
  83. }
  84. });
  85. $wg->wait(-1);
  86. $this->assertEquals($id, $data['id']);
  87. $this->assertInstanceOf(Exception::class, $result);
  88. $this->delete();
  89. }
  90. private function delete()
  91. {
  92. $model = new TestA();
  93. $model->connection('a')->destroy(null, true);
  94. }
  95. }