From e54408a1e8f75bf21d362a2201283e6152897f70 Mon Sep 17 00:00:00 2001 From: klinson Date: Wed, 8 Jan 2020 17:20:19 +0800 Subject: [PATCH 01/37] add transaction support, requires mongodb version V4.0 or more and deployment replica sets or sharded clusters transaction support create/insert,update,delete,etc operation Supports infinite-level nested transactions, but outside transaction rollbacks do not affect the commit of inside transactions ``` DB::beginTransaction(); DB::collection('users')->where('name', 'klinson')->update(['age' => 18]); DB::transaction(function () { DB::collection('users')->where('name', 'mongodb')->update(['age' => 30]); }); DB::rollBack(); ``` --- src/Jenssegers/Mongodb/Connection.php | 83 +++++++++ src/Jenssegers/Mongodb/Query/Builder.php | 68 ++++++-- tests/TransactionBuilderTest.php | 201 +++++++++++++++++++++ tests/TransactionTest.php | 211 +++++++++++++++++++++++ 4 files changed, 553 insertions(+), 10 deletions(-) create mode 100644 tests/TransactionBuilderTest.php create mode 100644 tests/TransactionTest.php diff --git a/src/Jenssegers/Mongodb/Connection.php b/src/Jenssegers/Mongodb/Connection.php index 7920ec9f6..03d2ef832 100644 --- a/src/Jenssegers/Mongodb/Connection.php +++ b/src/Jenssegers/Mongodb/Connection.php @@ -5,6 +5,9 @@ use Illuminate\Database\Connection as BaseConnection; use Illuminate\Support\Arr; use MongoDB\Client; +use MongoDB\Driver\ReadConcern; +use MongoDB\Driver\ReadPreference; +use MongoDB\Driver\WriteConcern; class Connection extends BaseConnection { @@ -20,6 +23,9 @@ class Connection extends BaseConnection */ protected $connection; + protected $session_key; // sessions会话列表当前会话数组key 随机生成 + protected $sessions = []; // 会话列表 + /** * Create a new database connection instance. * @param array $config @@ -254,4 +260,81 @@ public function __call($method, $parameters) { return call_user_func_array([$this->db, $method], $parameters); } + + /** + * create a session and start a transaction in session + * + * In version 4.0, MongoDB supports multi-document transactions on replica sets. + * In version 4.2, MongoDB introduces distributed transactions, which adds support for multi-document transactions on sharded clusters and incorporates the existing support for multi-document transactions on replica sets. + * To use transactions on MongoDB 4.2 deployments(replica sets and sharded clusters), clients must use MongoDB drivers updated for MongoDB 4.2. + * + * @see https://docs.mongodb.com/manual/core/transactions/ + * @author klinson + */ + public function beginTransaction() + { + $this->session_key = uniqid(); + $this->sessions[$this->session_key] = $this->connection->startSession(); + + $this->sessions[$this->session_key]->startTransaction([ + 'readPreference' => new ReadPreference(ReadPreference::RP_PRIMARY), + 'writeConcern' => new WriteConcern(1), + 'readConcern' => new ReadConcern(ReadConcern::LOCAL) + ]); + } + + /** + * commit transaction in this session and close this session + * @author klinson + */ + public function commit() + { + if ($session = $this->getSession()) { + $session->commitTransaction(); + $this->setLastSession(); + } + } + + /** + * rollback transaction in this session and close this session + * @author klinson + */ + public function rollBack() + { + if ($session = $this->getSession()) { + $session->abortTransaction(); + $this->setLastSession(); + } + } + + /** + * close this session and get last session key to session_key + * Why do it ? Because nested transactions + * @author klinson + */ + protected function setLastSession() + { + if ($session = $this->getSession()) { + $session->endSession(); + unset($this->sessions[$this->session_key]); + if (empty($this->sessions)) { + $this->session_key = null; + } else { + end($this->sessions); + $this->session_key = key($this->sessions); + } + } + } + + /** + * get now session if it has session + * @return \MongoDB\Driver\Session|null + * @author klinson + */ + public function getSession() + { + return ($this->session_key && isset($this->sessions[$this->session_key])) + ? $this->sessions[$this->session_key] + : null; + } } diff --git a/src/Jenssegers/Mongodb/Query/Builder.php b/src/Jenssegers/Mongodb/Query/Builder.php index 28d781a66..27d6c73d8 100644 --- a/src/Jenssegers/Mongodb/Query/Builder.php +++ b/src/Jenssegers/Mongodb/Query/Builder.php @@ -294,7 +294,7 @@ public function getFresh($columns = []) } } } - + // The _id field is mandatory when using grouping. if ($group && empty($group['_id'])) { $group['_id'] = null; @@ -338,6 +338,11 @@ public function getFresh($columns = []) $options = array_merge($options, $this->options); } + // if transaction in session + if ($session = $this->connection->getSession()) { + $options['session'] = $session; + } + // Execute aggregation $results = iterator_to_array($this->collection->aggregate($pipeline, $options)); @@ -348,13 +353,15 @@ public function getFresh($columns = []) // Return distinct results directly $column = isset($this->columns[0]) ? $this->columns[0] : '_id'; - // Execute distinct - if ($wheres) { - $result = $this->collection->distinct($column, $wheres); - } else { - $result = $this->collection->distinct($column); + $options = []; + // if transaction in session + if ($session = $this->connection->getSession()) { + $options['session'] = $session; } + // Execute distinct + $result = $this->collection->distinct($column, $wheres ?: [], $options); + return $this->useCollections ? new Collection($result) : $result; } // Normal query else { @@ -397,6 +404,11 @@ public function getFresh($columns = []) $options = array_merge($options, $this->options); } + // if transaction in session + if ($session = $this->connection->getSession()) { + $options['session'] = $session; + } + // Execute query and get MongoCursor $cursor = $this->collection->find($wheres, $options); @@ -561,7 +573,12 @@ public function insert(array $values) } // Batch insert - $result = $this->collection->insertMany($values); + $options = []; + // if transaction in session + if ($session = $this->connection->getSession()) { + $options['session'] = $session; + } + $result = $this->collection->insertMany($values, $options); return (1 == (int) $result->isAcknowledged()); } @@ -571,7 +588,12 @@ public function insert(array $values) */ public function insertGetId(array $values, $sequence = null) { - $result = $this->collection->insertOne($values); + $options = []; + // if transaction in session + if ($session = $this->connection->getSession()) { + $options['session'] = $session; + } + $result = $this->collection->insertOne($values, $options); if (1 == (int) $result->isAcknowledged()) { if ($sequence === null) { @@ -592,6 +614,10 @@ public function update(array $values, array $options = []) if (!Str::startsWith(key($values), '$')) { $values = ['$set' => $values]; } + // if transaction in session + if ($session = $this->connection->getSession()) { + $options['session'] = $session; + } return $this->performUpdate($values, $options); } @@ -614,6 +640,11 @@ public function increment($column, $amount = 1, array $extra = [], array $option $query->orWhereNotNull($column); }); + // if transaction in session + if ($session = $this->connection->getSession()) { + $options['session'] = $session; + } + return $this->performUpdate($query, $options); } @@ -673,7 +704,14 @@ public function delete($id = null) } $wheres = $this->compileWheres(); - $result = $this->collection->DeleteMany($wheres); + + $options = []; + // if transaction in session + if ($session = $this->connection->getSession()) { + $options['session'] = $session; + } + + $result = $this->collection->DeleteMany($wheres, $options); if (1 == (int) $result->isAcknowledged()) { return $result->getDeletedCount(); } @@ -698,7 +736,12 @@ public function from($collection, $as = null) */ public function truncate() { - $result = $this->collection->drop(); + $options = []; + // if transaction in session + if ($session = $this->connection->getSession()) { + $options['session'] = $session; + } + $result = $this->collection->drop($options); return (1 == (int) $result->ok); } @@ -826,6 +869,11 @@ protected function performUpdate($query, array $options = []) $options['multiple'] = true; } + // if transaction in session + if ($session = $this->connection->getSession()) { + $options['session'] = $session; + } + $wheres = $this->compileWheres(); $result = $this->collection->UpdateMany($wheres, $query, $options); if (1 == (int) $result->isAcknowledged()) { diff --git a/tests/TransactionBuilderTest.php b/tests/TransactionBuilderTest.php new file mode 100644 index 000000000..1dc645c4e --- /dev/null +++ b/tests/TransactionBuilderTest.php @@ -0,0 +1,201 @@ + 'klinson', 'age' => 20, 'title' => 'admin']; + protected $originData = ['name' => 'users', 'age' => 20, 'title' => 'user']; + + public function setUp(): void + { + parent::setUp(); + + DB::collection('users')->truncate(); + DB::collection('users')->insert($this->originData); + } + + public function tearDown(): void + { + DB::collection('users')->truncate(); + parent::tearDown(); + } + + public function testInsert() + { + /** rollback test */ + DB::beginTransaction(); + DB::collection('users')->insert($this->insertData); + DB::rollBack(); + $users = DB::collection('users')->where('name', $this->insertData['name'])->get(); + $this->assertCount(0, $users); + + /** commit test */ + DB::beginTransaction(); + DB::collection('users')->insert($this->insertData); + DB::commit(); + $users = DB::collection('users')->where('name', $this->insertData['name'])->get(); + $this->assertCount(1, $users); + } + + public function testInsertGetId() + { + /** rollback test */ + DB::beginTransaction(); + $user_id = DB::collection('users')->insertGetId($this->insertData); + DB::rollBack(); + $user_id = (string) $user_id; + $user = DB::collection('users')->find($user_id); + $this->assertNull($user); + + /** commit test */ + DB::beginTransaction(); + $user_id = DB::collection('users')->insertGetId($this->insertData); + DB::commit(); + $user_id = (string) $user_id; + $user = DB::collection('users')->find($user_id); + $this->assertEquals($this->insertData['name'], $user['name']); + } + + public function testUpdate() + { + /** rollback test */ + $new_age = $this->originData['age']+1; + DB::beginTransaction(); + DB::collection('users')->where('name', $this->originData['name'])->update(['age' => $new_age]); + DB::rollBack(); + $users = DB::collection('users')->where('name', $this->originData['name'])->where('age', $new_age)->get(); + $this->assertCount(0, $users); + + /** commit test */ + DB::beginTransaction(); + DB::collection('users')->where('name', $this->originData['name'])->update(['age' => $new_age]); + DB::commit(); + $users = DB::collection('users')->where('name', $this->originData['name'])->where('age', $new_age)->get(); + $this->assertCount(1, $users); + } + + public function testDelete() + { + /** rollback test */ + DB::beginTransaction(); + DB::collection('users')->where('name', $this->originData['name'])->delete(); + DB::rollBack(); + $users = DB::collection('users')->where('name', $this->originData['name'])->get(); + $this->assertCount(1, $users); + + /** commit test */ + DB::beginTransaction(); + DB::collection('users')->where('name', $this->originData['name'])->delete(); + DB::commit(); + $users = DB::collection('users')->where('name', $this->originData['name'])->get(); + $this->assertCount(0, $users); + } + + public function testIncrement() + { + /** rollback test */ + DB::beginTransaction(); + DB::collection('users')->where('name', $this->originData['name'])->increment('age'); + DB::rollBack(); + $user = DB::collection('users')->where('name', $this->originData['name'])->first(); + $this->assertEquals($this->originData['age'], $user['age']); + + /** commit test */ + DB::beginTransaction(); + DB::collection('users')->where('name', $this->originData['name'])->increment('age'); + DB::commit(); + $user = DB::collection('users')->where('name', $this->originData['name'])->first(); + $this->assertEquals($this->originData['age']+1, $user['age']); + } + + public function testDecrement() + { + /** rollback test */ + DB::beginTransaction(); + DB::collection('users')->where('name', $this->originData['name'])->decrement('age'); + DB::rollBack(); + $user = DB::collection('users')->where('name', $this->originData['name'])->first(); + $this->assertEquals($this->originData['age'], $user['age']); + + /** commit test */ + DB::beginTransaction(); + DB::collection('users')->where('name', $this->originData['name'])->decrement('age'); + DB::commit(); + $user = DB::collection('users')->where('name', $this->originData['name'])->first(); + $this->assertEquals($this->originData['age']-1, $user['age']); + } + + public function testQuery() + { + /** rollback test */ + DB::beginTransaction(); + $count = DB::collection('users')->count(); + $this->assertEquals(1, $count); + DB::collection('users')->insert($this->insertData); + $count = DB::collection('users')->count(); + $this->assertEquals(2, $count); + DB::rollBack(); + $count = DB::collection('users')->count(); + $this->assertEquals(1, $count); + + /** commit test */ + DB::beginTransaction(); + $count = DB::collection('users')->count(); + $this->assertEquals(1, $count); + DB::collection('users')->insert($this->insertData); + $count = DB::collection('users')->count(); + $this->assertEquals(2, $count); + DB::commit(); + $count = DB::collection('users')->count(); + $this->assertEquals(2, $count); + } + + public function testTransaction() + { + $count = DB::collection('users')->count(); + $this->assertEquals(1, $count); + + $new_age = $this->originData['age'] + 1; + DB::transaction(function () use ($new_age) { + DB::collection('users')->insert($this->insertData); + DB::collection('users')->where('name', $this->originData['name'])->update(['age' => $new_age]); + }); + $count = DB::collection('users')->count(); + $this->assertEquals(2, $count); + + $checkInsert = DB::collection('users')->where('name', $this->insertData['name'])->first(); + $this->assertNotNull($checkInsert); + $this->assertEquals($this->insertData['age'], $checkInsert['age']); + + $checkUpdate = DB::collection('users')->where('name', $this->originData['name'])->first(); + $this->assertEquals($new_age, $checkUpdate['age']); + } + + /** + * Supports infinite-level nested transactions, but outside transaction rollbacks do not affect the commit of inside transactions + */ + public function TestNestingTransaction() + { + DB::collection('users')->insert($this->insertData); + $new_age1 = $this->originData['age'] + 1; + $new_age2 = $this->insertData['age'] + 1; + /** outside transaction */ + DB::beginTransaction(); + + DB::collection('users')->where('name', $this->originData['name'])->update(['age' => $new_age1]); + + /** inside transaction */ + DB::transaction(function () use ($new_age2) { + DB::collection('users')->where('name', $this->insertData['name'])->update(['age' => $new_age2]); + }); + + DB::rollBack(); + + $check1 = DB::collection('users')->where('name', $this->originData['name'])->first(); + $check2 = DB::collection('users')->where('name', $this->insertData['name'])->first(); + $this->assertNotEquals($new_age1, $check1['age']); + $this->assertEquals($new_age2, $check2['age']); + } +} diff --git a/tests/TransactionTest.php b/tests/TransactionTest.php new file mode 100644 index 000000000..d64fcd170 --- /dev/null +++ b/tests/TransactionTest.php @@ -0,0 +1,211 @@ + 'klinson', 'age' => 20, 'title' => 'admin']; + protected $originData = ['name' => 'users', 'age' => 20, 'title' => 'user']; + + public function setUp(): void + { + parent::setUp(); + User::truncate(); + User::create($this->originData); + } + + public function tearDown(): void + { + User::truncate(); + parent::tearDown(); + } + + public function testCreate() + { + /** rollback test */ + DB::beginTransaction(); + $user = User::create($this->insertData); + DB::rollBack(); + $this->assertInstanceOf(\Jenssegers\Mongodb\Eloquent\Model::class, $user); + $this->assertTrue($user->exists); + $this->assertEquals($this->insertData['name'], $user->name); + + $check = User::find($user->_id); + $this->assertNull($check); + + /** commit test */ + DB::beginTransaction(); + $user = User::create($this->insertData); + DB::commit(); + $this->assertInstanceOf(\Jenssegers\Mongodb\Eloquent\Model::class, $user); + $this->assertTrue($user->exists); + $this->assertEquals($this->insertData['name'], $user->name); + + $check = User::find($user->_id); + $this->assertNotNull($check); + $this->assertEquals($user->name, $check->name); + } + + public function testInsert() + { + /** rollback test */ + DB::beginTransaction(); + $user = new User; + $user->name = $this->insertData['name']; + $user->title = $this->insertData['title']; + $user->age = $this->insertData['age']; + $user->save(); + DB::rollBack(); + + $this->assertTrue($user->exists); + $this->assertTrue(isset($user->_id)); + $this->assertIsString($user->_id); + + $check = User::find($user->_id); + $this->assertNull($check); + + /** commit test */ + DB::beginTransaction(); + $user = new User; + $user->name = $this->insertData['name']; + $user->title = $this->insertData['title']; + $user->age = $this->insertData['age']; + $user->save(); + DB::commit(); + + $this->assertTrue($user->exists); + $this->assertTrue(isset($user->_id)); + $this->assertIsString($user->_id); + + $check = User::find($user->_id); + $this->assertNotNull($check); + $this->assertEquals($check->name, $user->name); + $this->assertEquals($check->age, $user->age); + $this->assertEquals($check->title, $user->title); + } + + public function testInsertWithId(): void + { + $id = 1; + $check = User::find($id); + $this->assertNull($check); + + /** rollback test */ + DB::beginTransaction(); + $user = new User; + $user->_id = $id; + $user->name = $this->insertData['name']; + $user->title = $this->insertData['title']; + $user->age = $this->insertData['age']; + $user->save(); + DB::rollBack(); + + $this->assertTrue($user->exists); + $this->assertEquals($id, $user->_id); + $check = User::find($id); + $this->assertNull($check); + + /** commit test */ + DB::beginTransaction(); + $user = new User; + $user->_id = $id; + $user->name = $this->insertData['name']; + $user->title = $this->insertData['title']; + $user->age = $this->insertData['age']; + $user->save(); + DB::commit(); + + $this->assertTrue($user->exists); + $this->assertEquals($id, $user->_id); + $check = User::find($id); + $this->assertNotNull($check); + $this->assertEquals($check->name, $user->name); + $this->assertEquals($check->age, $user->age); + $this->assertEquals($check->title, $user->title); + } + + public function testUpdate() + { + /** rollback test */ + $new_age = $this->insertData['age'] + 1; + $user1 = User::create($this->insertData); + $user2 = User::create($this->insertData); + DB::beginTransaction(); + $user1->age = $new_age; + $user1->save(); + $user2->update(['age' => $new_age]); + DB::rollBack(); + $this->assertEquals($new_age, $user1->age); + $this->assertEquals($new_age, $user2->age); + + $check1 = User::find($user1->_id); + $check2 = User::find($user2->_id); + $this->assertEquals($this->insertData['age'], $check1->age); + $this->assertEquals($this->insertData['age'], $check2->age); + + /** commit test */ + User::truncate(); + $user1 = User::create($this->insertData); + $user2 = User::create($this->insertData); + DB::beginTransaction(); + $user1->age = $new_age; + $user1->save(); + $user2->update(['age' => $new_age]); + DB::commit(); + $this->assertEquals($new_age, $user1->age); + $this->assertEquals($new_age, $user2->age); + + $check1 = User::find($user1->_id); + $check2 = User::find($user2->_id); + $this->assertEquals($new_age, $check1->age); + $this->assertEquals($new_age, $check2->age); + } + + public function testDelete() + { + /** rollback test */ + $user1 = User::create($this->insertData); + $user2 = User::create($this->insertData); + DB::beginTransaction(); + $user1->delete(); + User::destroy((string) $user2->_id); + DB::rollBack(); + $check1 = User::find($user1->_id); + $check2 = User::find($user2->_id); + $this->assertNotNull($check1); + $this->assertNotNull($check2); + + /** commit test */ + User::truncate(); + $user1 = User::create($this->insertData); + $user2 = User::create($this->insertData); + DB::beginTransaction(); + $user1->delete(); + User::destroy((string) $user2->_id); + DB::commit(); + $check1 = User::find($user1->_id); + $check2 = User::find($user2->_id); + $this->assertNull($check1); + $this->assertNull($check2); + } + + public function testTransaction() + { + $count = User::count(); + $this->assertEquals(1, $count); + $new_age = $this->originData['age'] + 1; + DB::transaction(function () use ($new_age) { + User::create($this->insertData); + User::where($this->originData['name'])->update(['age' => $new_age]); + }); + $count = User::count(); + $this->assertEquals(2, $count); + + $checkInsert = User::where($this->insertData['name'])->first(); + $this->assertNotNull($checkInsert); + + $checkUpdate = User::where($this->originData['name'])->first(); + $this->assertEquals($new_age, $checkUpdate->age); + } +} From 9a01d2325d6eaf510ea5be62daf53872813986d7 Mon Sep 17 00:00:00 2001 From: klinson Date: Wed, 8 Jan 2020 18:55:55 +0800 Subject: [PATCH 02/37] format code --- tests/TransactionBuilderTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/TransactionBuilderTest.php b/tests/TransactionBuilderTest.php index 1dc645c4e..77f3b8ba5 100644 --- a/tests/TransactionBuilderTest.php +++ b/tests/TransactionBuilderTest.php @@ -61,7 +61,7 @@ public function testInsertGetId() public function testUpdate() { /** rollback test */ - $new_age = $this->originData['age']+1; + $new_age = $this->originData['age'] + 1; DB::beginTransaction(); DB::collection('users')->where('name', $this->originData['name'])->update(['age' => $new_age]); DB::rollBack(); @@ -107,7 +107,7 @@ public function testIncrement() DB::collection('users')->where('name', $this->originData['name'])->increment('age'); DB::commit(); $user = DB::collection('users')->where('name', $this->originData['name'])->first(); - $this->assertEquals($this->originData['age']+1, $user['age']); + $this->assertEquals($this->originData['age'] + 1, $user['age']); } public function testDecrement() @@ -124,7 +124,7 @@ public function testDecrement() DB::collection('users')->where('name', $this->originData['name'])->decrement('age'); DB::commit(); $user = DB::collection('users')->where('name', $this->originData['name'])->first(); - $this->assertEquals($this->originData['age']-1, $user['age']); + $this->assertEquals($this->originData['age'] - 1, $user['age']); } public function testQuery() From 64b415611a41c1531c5fdf2773224bc75268fab6 Mon Sep 17 00:00:00 2001 From: klinson Date: Thu, 9 Jan 2020 18:39:18 +0800 Subject: [PATCH 03/37] add mongodb(replica set) environment into docker configuration --- MongoReplsetDockerFile | 5 ++++ docker-compose.yml | 46 ++++++++++++++++++++++++++++++++ mongo-replset-init.sh | 23 ++++++++++++++++ tests/TestCase.php | 1 + tests/TransactionBuilderTest.php | 7 +++++ tests/TransactionTest.php | 9 +++++++ tests/config/database.php | 13 +++++++++ tests/models/User.php | 2 +- 8 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 MongoReplsetDockerFile create mode 100644 mongo-replset-init.sh diff --git a/MongoReplsetDockerFile b/MongoReplsetDockerFile new file mode 100644 index 000000000..652d9bb96 --- /dev/null +++ b/MongoReplsetDockerFile @@ -0,0 +1,5 @@ +FROM mongo + +ADD mongo-replset-init.sh /usr/local/bin/ + +RUN chmod +x /usr/local/bin/mongo-replset-init.sh diff --git a/docker-compose.yml b/docker-compose.yml index c6f20163e..c3f2b9ce3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,6 +12,9 @@ services: depends_on: - mongodb - mysql + - mongo1 + - mongo2 + - mongo3 mysql: container_name: mysql @@ -30,3 +33,46 @@ services: - 27017:27017 logging: driver: none + + mongo1: + hostname: mongo1 + container_name: mongo1 + image: mongo + restart: always + expose: + - 27017 + ports: + - 27018:27017 + command: '--quiet --bind_ip_all --replSet rs0' + + mongo2: + hostname: mongo2 + container_name: mongo2 + image: mongo + restart: always + expose: + - 27017 + ports: + - 27019:27017 + command: '--quiet --bind_ip_all --replSet rs0' + + mongo3: + hostname: mongo3 + container_name: mongo3 + image: mongo + restart: always + expose: + - 27017 + ports: + - 27020:27017 + command: '--quiet --bind_ip_all --replSet rs0' + + mongoreplret: + build: + context: . + dockerfile: MongoReplsetDockerFile + depends_on: + - mongo1 + - mongo2 + - mongo3 + entrypoint: ["sh", "-c", "mongo-replset-init.sh"] diff --git a/mongo-replset-init.sh b/mongo-replset-init.sh new file mode 100644 index 000000000..d5a95b555 --- /dev/null +++ b/mongo-replset-init.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +echo "prepare rs initiating" + +check_db_status() { + mongo1=$(mongo --host mongo1 --port 27017 --eval "db.stats().ok" | tail -n1 | grep -E '(^|\s)1($|\s)') + mongo2=$(mongo --host mongo2 --port 27017 --eval "db.stats().ok" | tail -n1 | grep -E '(^|\s)1($|\s)') + mongo3=$(mongo --host mongo3 --port 27017 --eval "db.stats().ok" | tail -n1 | grep -E '(^|\s)1($|\s)') + if [[ $mongo1 == 1 ]] && [[ $mongo2 == 1 ]] && [[ $mongo3 == 1 ]]; then + init_rs + else + check_db_status + fi +} + +init_rs() { + ret=$(mongo --host mongo1 --port 27017 --eval "rs.initiate({ _id: 'rs0', members: [{ _id: 0, host: 'mongo1:27017' }, { _id: 1, host: 'mongo2:27017' }, { _id: 2, host: 'mongo3:27017' } ] })" > /dev/null 2>&1) +} + +check_db_status > /dev/null 2>&1 + +echo "rs initiating finished" +exit 0 diff --git a/tests/TestCase.php b/tests/TestCase.php index a455b8576..fb7cb9a2f 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -53,6 +53,7 @@ protected function getEnvironmentSetUp($app) $app['config']->set('database.connections.mongodb', $config['connections']['mongodb']); $app['config']->set('database.connections.mongodb2', $config['connections']['mongodb']); $app['config']->set('database.connections.dsn_mongodb', $config['connections']['dsn_mongodb']); + $app['config']->set('database.connections.mongodb_replset', $config['connections']['mongodb_replset']); $app['config']->set('auth.model', 'User'); $app['config']->set('auth.providers.users.model', 'User'); diff --git a/tests/TransactionBuilderTest.php b/tests/TransactionBuilderTest.php index 77f3b8ba5..7b5a31ff4 100644 --- a/tests/TransactionBuilderTest.php +++ b/tests/TransactionBuilderTest.php @@ -7,11 +7,17 @@ class TransactionBuilderTest extends TestCase { protected $insertData = ['name' => 'klinson', 'age' => 20, 'title' => 'admin']; protected $originData = ['name' => 'users', 'age' => 20, 'title' => 'user']; + protected $connection = 'mongodb_replset'; + protected $originConnection = 'mongodb'; public function setUp(): void { parent::setUp(); + /** change connection to seplset? because the transaction needs */ + $this->originConnection = DB::getDefaultConnection(); + DB::setDefaultConnection($this->connection); + DB::collection('users')->truncate(); DB::collection('users')->insert($this->originData); } @@ -19,6 +25,7 @@ public function setUp(): void public function tearDown(): void { DB::collection('users')->truncate(); + DB::setDefaultConnection($this->originConnection); parent::tearDown(); } diff --git a/tests/TransactionTest.php b/tests/TransactionTest.php index d64fcd170..6fa615aca 100644 --- a/tests/TransactionTest.php +++ b/tests/TransactionTest.php @@ -7,10 +7,17 @@ class TransactionTest extends TestCase { protected $insertData = ['name' => 'klinson', 'age' => 20, 'title' => 'admin']; protected $originData = ['name' => 'users', 'age' => 20, 'title' => 'user']; + protected $connection = 'mongodb_replset'; + protected $originConnection = 'mongodb'; public function setUp(): void { parent::setUp(); + + /** change connection to seplset? because the transaction needs */ + $this->originConnection = DB::getDefaultConnection(); + DB::setDefaultConnection($this->connection); + User::truncate(); User::create($this->originData); } @@ -18,6 +25,8 @@ public function setUp(): void public function tearDown(): void { User::truncate(); + DB::setDefaultConnection($this->originConnection); + parent::tearDown(); } diff --git a/tests/config/database.php b/tests/config/database.php index 23f8ca990..7bc3d4d04 100644 --- a/tests/config/database.php +++ b/tests/config/database.php @@ -14,6 +14,19 @@ 'database' => env('MONGO_DATABASE', 'unittest'), ], + 'mongodb_replset' => [ + 'driver' => 'mongodb', + 'host' => [ + 'mongo1:27017', + 'mongo2:27017', + 'mongo3:27017', + ], + 'database' => env('MONGO_DATABASE', 'unittest'), + 'options' => [ + 'replicaSet' => 'rs0' + ] + ], + 'dsn_mongodb' => [ 'driver' => 'mongodb', 'dsn' => "mongodb://$mongoHost:$mongoPort", diff --git a/tests/models/User.php b/tests/models/User.php index 1217af762..56cee1636 100644 --- a/tests/models/User.php +++ b/tests/models/User.php @@ -23,7 +23,7 @@ class User extends Eloquent implements AuthenticatableContract, CanResetPassword { use Authenticatable, CanResetPassword, HybridRelations, Notifiable; - protected $connection = 'mongodb'; +// protected $connection = 'mongodb'; protected $dates = ['birthday', 'entry.date']; protected static $unguarded = true; From 34b1a98ea53cac949c1beb1206106f500a304506 Mon Sep 17 00:00:00 2001 From: klinson Date: Thu, 9 Jan 2020 18:41:25 +0800 Subject: [PATCH 04/37] must be compatible with Illuminate\Database\Connection::rollBack($toLevel = NULL) --- src/Jenssegers/Mongodb/Connection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Jenssegers/Mongodb/Connection.php b/src/Jenssegers/Mongodb/Connection.php index 03d2ef832..82914a713 100644 --- a/src/Jenssegers/Mongodb/Connection.php +++ b/src/Jenssegers/Mongodb/Connection.php @@ -299,7 +299,7 @@ public function commit() * rollback transaction in this session and close this session * @author klinson */ - public function rollBack() + public function rollBack($toLevel = null) { if ($session = $this->getSession()) { $session->abortTransaction(); From 84850a9b85cc4f8eaf6edbfde54f432628311abd Mon Sep 17 00:00:00 2001 From: klinson Date: Thu, 9 Jan 2020 18:54:20 +0800 Subject: [PATCH 05/37] add transaction usage into readme.md --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index a6fc96e39..1a7f2d440 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Table of contents * [Eloquent](#eloquent) * [Optional: Alias](#optional-alias) * [Query Builder](#query-builder) +* [Transaction](#transaction) * [Schema](#schema) * [Extensions](#extensions) * [Troubleshooting](#troubleshooting) @@ -241,6 +242,26 @@ $user = DB::connection('mongodb')->collection('users')->get(); Read more about the query builder on http://laravel.com/docs/queries +Transaction +------------- +Transaction requires mongodb version V4.0 or more and deployment replica sets or sharded clusters. + +Transaction supports create/insert,update,delete,etc operation. + +Transaction supports infinite-level nested transactions, but outside transaction rollbacks do not affect the commit of inside transactions. +```php +DB::beginTransaction(); + +User::create(['name' => 'klinson', 'age' => 20, 'title' => 'admin']); + +DB::transaction(function () { +    DB::collection('users')->where('name', 'klinson')->update(['age' => 20]); +}); + +DB::rollBack(); +//DB::commit(); +``` + Schema ------ From bedaaa85733e201cb267850a7f3c71604a80b9c6 Mon Sep 17 00:00:00 2001 From: klinson Date: Fri, 10 Jan 2020 11:16:16 +0800 Subject: [PATCH 06/37] update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 736c4c86e..7d91a14b0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,7 @@ cache: install: - docker version - - sudo pip install docker-compose + - sudo curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose - docker-compose version - docker-compose build --build-arg PHP_VERSION=${PHP_VERSION} - docker-compose run --rm tests composer install --no-interaction From b03091402652eebfeb2b3a09a70a969f3410b902 Mon Sep 17 00:00:00 2001 From: klinson Date: Mon, 13 Jan 2020 17:17:10 +0800 Subject: [PATCH 07/37] update database.conf --- tests/config/database.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/config/database.php b/tests/config/database.php index 7bc3d4d04..63ec1d37a 100644 --- a/tests/config/database.php +++ b/tests/config/database.php @@ -23,7 +23,8 @@ ], 'database' => env('MONGO_DATABASE', 'unittest'), 'options' => [ - 'replicaSet' => 'rs0' + 'replicaSet' => 'rs0', + 'serverSelectionTryOnce' => false, ] ], From 163b41dfdc2a93a291ab67485f8c76b27f4b6484 Mon Sep 17 00:00:00 2001 From: klinson Date: Mon, 13 Jan 2020 17:17:31 +0800 Subject: [PATCH 08/37] update .travis.yml --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7d91a14b0..82bb0836b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,4 +24,5 @@ install: - docker-compose run --rm tests composer install --no-interaction script: - - docker-compose run --rm tests ./vendor/bin/phpunit --coverage-clover ./clover.xml + - docker-compose up -d + - docker-compose exec tests ./vendor/bin/phpunit From 92c1e0780a646607a7a121fa48f60eb205a3ac5a Mon Sep 17 00:00:00 2001 From: klinson Date: Mon, 13 Jan 2020 17:17:56 +0800 Subject: [PATCH 09/37] update docker-compose.yml --- docker-compose.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index c3f2b9ce3..db4e52271 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,6 +15,8 @@ services: - mongo1 - mongo2 - mongo3 + stdin_open: true + tty: true mysql: container_name: mysql From caa61ea184796f1d7fb6f12aa48b771bf610e196 Mon Sep 17 00:00:00 2001 From: klinson Date: Fri, 17 Jan 2020 18:32:22 +0800 Subject: [PATCH 10/37] Update src/Jenssegers/Mongodb/Connection.php Co-Authored-By: Stas --- src/Jenssegers/Mongodb/Connection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Jenssegers/Mongodb/Connection.php b/src/Jenssegers/Mongodb/Connection.php index 82914a713..664d5d74d 100644 --- a/src/Jenssegers/Mongodb/Connection.php +++ b/src/Jenssegers/Mongodb/Connection.php @@ -333,7 +333,7 @@ protected function setLastSession() */ public function getSession() { - return ($this->session_key && isset($this->sessions[$this->session_key])) + return $this->sessions[$this->session_key] ?? null; ? $this->sessions[$this->session_key] : null; } From 7d96c3e7b9fe1611e28015a31d5f9ece52ca0561 Mon Sep 17 00:00:00 2001 From: klinson Date: Fri, 7 Feb 2020 21:05:20 +0800 Subject: [PATCH 11/37] fixbug Connection.php --- src/Jenssegers/Mongodb/Connection.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Jenssegers/Mongodb/Connection.php b/src/Jenssegers/Mongodb/Connection.php index 664d5d74d..815c8c6eb 100644 --- a/src/Jenssegers/Mongodb/Connection.php +++ b/src/Jenssegers/Mongodb/Connection.php @@ -334,7 +334,5 @@ protected function setLastSession() public function getSession() { return $this->sessions[$this->session_key] ?? null; - ? $this->sessions[$this->session_key] - : null; } } From 10bda056f878497d1e6869371b5e3f4bb11e68f2 Mon Sep 17 00:00:00 2001 From: klinson Date: Fri, 7 Feb 2020 22:01:56 +0800 Subject: [PATCH 12/37] add transaction into README.md --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 1f13ea261..3c0f88a89 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ This package adds functionalities to the Eloquent model and Query builder for Mo - [Query Builder](#query-builder) - [Basic Usage](#basic-usage-2) - [Available operations](#available-operations) + - [Transaction](#transaction) - [Schema](#schema) - [Basic Usage](#basic-usage-3) - [Geospatial indexes](#geospatial-indexes) @@ -936,6 +937,23 @@ If you are familiar with [Eloquent Queries](http://laravel.com/docs/queries), th ### Available operations To see the available operations, check the [Eloquent](#eloquent) section. +Transaction +------------- +Transaction requires mongodb version V4.0 or more and deployment replica sets or sharded clusters. + +Transaction supports create/insert,update,delete,etc operation. + +Transaction supports infinite-level nested transactions, but outside transaction rollbacks do not affect the commit of inside transactions. +```php +DB::beginTransaction(); +User::create(['name' => 'klinson', 'age' => 20, 'title' => 'admin']); +DB::transaction(function () { + DB::collection('users')->where('name', 'klinson')->update(['age' => 20]); +}); +DB::rollBack(); +//DB::commit(); +``` + Schema ------ The database driver also has (limited) schema builder support. You can easily manipulate collections and set indexes. From 85a0be86306ef428b6738176e187ebb65835b3c3 Mon Sep 17 00:00:00 2001 From: klinson Date: Fri, 7 Feb 2020 22:29:34 +0800 Subject: [PATCH 13/37] add replset mongodb tag --- MongoReplsetDockerFile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MongoReplsetDockerFile b/MongoReplsetDockerFile index 652d9bb96..fa5a16e84 100644 --- a/MongoReplsetDockerFile +++ b/MongoReplsetDockerFile @@ -1,4 +1,4 @@ -FROM mongo +FROM mongo:4.2 ADD mongo-replset-init.sh /usr/local/bin/ From b39251c16f2925ce92965c8beda4e41addbe316a Mon Sep 17 00:00:00 2001 From: klinson Date: Sun, 9 Feb 2020 16:05:51 +0800 Subject: [PATCH 14/37] Remove travis from PR please --- .travis.yml | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 82bb0836b..000000000 --- a/.travis.yml +++ /dev/null @@ -1,28 +0,0 @@ -language: minimal - -matrix: - include: - - name: "7.1" - env: PHP_VERSION=7.1 - - name: "7.2" - env: PHP_VERSION=7.2 - - name: "7.3" - env: PHP_VERSION=7.3 - -services: - - docker - -cache: - directories: - - $HOME/.composer/cache - -install: - - docker version - - sudo curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose - - docker-compose version - - docker-compose build --build-arg PHP_VERSION=${PHP_VERSION} - - docker-compose run --rm tests composer install --no-interaction - -script: - - docker-compose up -d - - docker-compose exec tests ./vendor/bin/phpunit From fe610562d887d504468358e5088f58be55d7cd10 Mon Sep 17 00:00:00 2001 From: klinson Date: Fri, 14 Feb 2020 02:28:52 +0800 Subject: [PATCH 15/37] remove author tag and comments in Chinese language --- src/Jenssegers/Mongodb/Connection.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Jenssegers/Mongodb/Connection.php b/src/Jenssegers/Mongodb/Connection.php index 815c8c6eb..1893c1c4a 100644 --- a/src/Jenssegers/Mongodb/Connection.php +++ b/src/Jenssegers/Mongodb/Connection.php @@ -23,8 +23,8 @@ class Connection extends BaseConnection */ protected $connection; - protected $session_key; // sessions会话列表当前会话数组key 随机生成 - protected $sessions = []; // 会话列表 + protected $session_key; + protected $sessions = []; /** * Create a new database connection instance. @@ -269,7 +269,6 @@ public function __call($method, $parameters) * To use transactions on MongoDB 4.2 deployments(replica sets and sharded clusters), clients must use MongoDB drivers updated for MongoDB 4.2. * * @see https://docs.mongodb.com/manual/core/transactions/ - * @author klinson */ public function beginTransaction() { @@ -285,7 +284,6 @@ public function beginTransaction() /** * commit transaction in this session and close this session - * @author klinson */ public function commit() { @@ -297,7 +295,6 @@ public function commit() /** * rollback transaction in this session and close this session - * @author klinson */ public function rollBack($toLevel = null) { @@ -310,7 +307,6 @@ public function rollBack($toLevel = null) /** * close this session and get last session key to session_key * Why do it ? Because nested transactions - * @author klinson */ protected function setLastSession() { @@ -329,7 +325,6 @@ protected function setLastSession() /** * get now session if it has session * @return \MongoDB\Driver\Session|null - * @author klinson */ public function getSession() { From 3029e36592ce9738278cee3580520a22227b3551 Mon Sep 17 00:00:00 2001 From: klinson Date: Fri, 14 Feb 2020 02:45:29 +0800 Subject: [PATCH 16/37] improved function docblocks of transaction --- README.md | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3c0f88a89..a2bee0b14 100644 --- a/README.md +++ b/README.md @@ -938,11 +938,35 @@ If you are familiar with [Eloquent Queries](http://laravel.com/docs/queries), th To see the available operations, check the [Eloquent](#eloquent) section. Transaction -------------- -Transaction requires mongodb version V4.0 or more and deployment replica sets or sharded clusters. +------- +Transaction requires mongodb version V4.0 or more and deployment replica sets or sharded clusters.You can look at its speciality [in the MongoDB docs](https://docs.mongodb.com/manual/core/transactions/) + +### Basic Usage Transaction supports create/insert,update,delete,etc operation. +```php +DB::transaction(function () { + User::create(['name' => 'klinson', 'age' => 19, 'title' => 'admin', 'email' => 'klinsonup@gmail.com']); + DB::collection('users')->where('name', 'klinson')->update(['age' => 20]); + DB::collection('users')->where('name', 'klinson')->delete(); +}); +``` + +```php +// begin a transaction +DB::beginTransaction(); +User::create(['name' => 'klinson', 'age' => 19, 'title' => 'admin', 'email' => 'klinsonup@gmail.com']); +DB::collection('users')->where('name', 'klinson')->update(['age' => 20]); +DB::collection('users')->where('name', 'klinson')->delete(); + +// you can commit your changes +DB::commit(); + +// you can also rollback them +//DB::rollBack(); +``` + Transaction supports infinite-level nested transactions, but outside transaction rollbacks do not affect the commit of inside transactions. ```php DB::beginTransaction(); @@ -951,7 +975,6 @@ DB::transaction(function () { DB::collection('users')->where('name', 'klinson')->update(['age' => 20]); }); DB::rollBack(); -//DB::commit(); ``` Schema From 722141758637e2191df1a60c78636bf2e7c0e98f Mon Sep 17 00:00:00 2001 From: klinson Date: Sun, 28 Jun 2020 18:38:57 +0800 Subject: [PATCH 17/37] add another testsuite for transactional tests in phpunit.xml --- phpunit.xml.dist | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 4da34b41d..51f570dfb 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -25,6 +25,10 @@ tests/QueryBuilderTest.php tests/QueryTest.php + + tests/TransactionBuilderTest.php + tests/TransactionTest.php + tests/ModelTest.php tests/RelationsTest.php From 1b90047282b1039a08eb7e1b2050eb6e94a41bf6 Mon Sep 17 00:00:00 2001 From: klinson Date: Wed, 1 Jul 2020 20:49:56 +0800 Subject: [PATCH 18/37] optimized code --- src/Jenssegers/Mongodb/Query/Builder.php | 55 +++++++++++------------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/src/Jenssegers/Mongodb/Query/Builder.php b/src/Jenssegers/Mongodb/Query/Builder.php index 101171452..5fd02f6f2 100644 --- a/src/Jenssegers/Mongodb/Query/Builder.php +++ b/src/Jenssegers/Mongodb/Query/Builder.php @@ -358,9 +358,7 @@ public function getFresh($columns = [], $returnLazy = false) } // if transaction in session - if ($session = $this->connection->getSession()) { - $options['session'] = $session; - } + $options = $this->setSession($options); // Execute aggregation $results = iterator_to_array($this->collection->aggregate($pipeline, $options)); @@ -374,9 +372,7 @@ public function getFresh($columns = [], $returnLazy = false) $options = []; // if transaction in session - if ($session = $this->connection->getSession()) { - $options['session'] = $session; - } + $options = $this->setSession($options); // Execute distinct $result = $this->collection->distinct($column, $wheres ?: [], $options); @@ -426,9 +422,7 @@ public function getFresh($columns = [], $returnLazy = false) } // if transaction in session - if ($session = $this->connection->getSession()) { - $options['session'] = $session; - } + $options = $this->setSession($options); // Execute query and get MongoCursor $cursor = $this->collection->find($wheres, $options); @@ -604,9 +598,8 @@ public function insert(array $values) // Batch insert $options = []; // if transaction in session - if ($session = $this->connection->getSession()) { - $options['session'] = $session; - } + $options = $this->setSession($options); + $result = $this->collection->insertMany($values, $options); return (1 == (int) $result->isAcknowledged()); @@ -619,9 +612,8 @@ public function insertGetId(array $values, $sequence = null) { $options = []; // if transaction in session - if ($session = $this->connection->getSession()) { - $options['session'] = $session; - } + $options = $this->setSession($options); + $result = $this->collection->insertOne($values, $options); if (1 == (int) $result->isAcknowledged()) { @@ -644,9 +636,7 @@ public function update(array $values, array $options = []) $values = ['$set' => $values]; } // if transaction in session - if ($session = $this->connection->getSession()) { - $options['session'] = $session; - } + $options = $this->setSession($options); return $this->performUpdate($values, $options); } @@ -670,9 +660,7 @@ public function increment($column, $amount = 1, array $extra = [], array $option }); // if transaction in session - if ($session = $this->connection->getSession()) { - $options['session'] = $session; - } + $options = $this->setSession($options); return $this->performUpdate($query, $options); } @@ -736,9 +724,7 @@ public function delete($id = null) $options = []; // if transaction in session - if ($session = $this->connection->getSession()) { - $options['session'] = $session; - } + $options = $this->setSession($options); $result = $this->collection->DeleteMany($wheres, $options); if (1 == (int) $result->isAcknowledged()) { @@ -769,9 +755,7 @@ public function truncate() 'typeMap' => ['root' => 'object', 'document' => 'object'], ]; // if transaction in session - if ($session = $this->connection->getSession()) { - $options['session'] = $session; - } + $options = $this->setSession($options); $result = $this->collection->drop($options); @@ -902,9 +886,7 @@ protected function performUpdate($query, array $options = []) } // if transaction in session - if ($session = $this->connection->getSession()) { - $options['session'] = $session; - } + $options = $this->setSession($options); $wheres = $this->compileWheres(); $result = $this->collection->UpdateMany($wheres, $query, $options); @@ -1238,6 +1220,19 @@ public function options(array $options) return $this; } + /** + * set session for the transaction + * @param $session + * @return mixed + */ + protected function setSession($options) + { + if ($session = $this->connection->getSession()) { + $options['session'] = $session; + } + return $options; + } + /** * @inheritdoc */ From a5d0858fce33219b714c0410b70dfb694e8201d1 Mon Sep 17 00:00:00 2001 From: klinson Date: Tue, 21 Jul 2020 15:05:01 +0800 Subject: [PATCH 19/37] update ci and tests configs --- MongoReplsetDockerFile | 5 -- docker-compose.yml | 91 ++++++++++++++++++------------- mongo-replset-init.sh | 52 +++++++++++------- tests/TestCase.php | 2 +- tests/TransactionBuilderTest.php | 14 ++++- tests/TransactionTest.php | 93 ++++++++++++++++++-------------- tests/config/database.php | 22 ++++---- tests/models/User.php | 2 +- 8 files changed, 166 insertions(+), 115 deletions(-) delete mode 100644 MongoReplsetDockerFile diff --git a/MongoReplsetDockerFile b/MongoReplsetDockerFile deleted file mode 100644 index fa5a16e84..000000000 --- a/MongoReplsetDockerFile +++ /dev/null @@ -1,5 +0,0 @@ -FROM mongo:4.2 - -ADD mongo-replset-init.sh /usr/local/bin/ - -RUN chmod +x /usr/local/bin/mongo-replset-init.sh diff --git a/docker-compose.yml b/docker-compose.yml index db4e52271..0057eea30 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,11 +10,12 @@ services: - .:/code working_dir: /code depends_on: - - mongodb - - mysql - - mongo1 - - mongo2 - - mongo3 + - mongodb + - mongodb_repl + - mongodb_repl_2 + - mongodb_repl_3 + - mongo_repl_init + - mysql stdin_open: true tty: true @@ -36,45 +37,61 @@ services: logging: driver: none - mongo1: - hostname: mongo1 - container_name: mongo1 - image: mongo + mongodb_repl: + container_name: mongodb_repl + image: mongo:4.2.5 restart: always - expose: - - 27017 ports: - - 27018:27017 - command: '--quiet --bind_ip_all --replSet rs0' + - "27018:27018" + entrypoint: [ "/usr/bin/mongod", "--quiet", "--bind_ip_all", "--port", "27018", "--replSet", "rs" ] + depends_on: + - mongodb_repl_2 + - mongodb_repl_3 + links: + - mongodb_repl_2:mongodb_repl_2 + - mongodb_repl_3:mongodb_repl_3 + logging: + driver: none - mongo2: - hostname: mongo2 - container_name: mongo2 - image: mongo + mongodb_repl_2: + container_name: mongodb_repl_2 + image: mongo:4.2.5 restart: always - expose: - - 27017 ports: - - 27019:27017 - command: '--quiet --bind_ip_all --replSet rs0' + - "27019:27018" + entrypoint: [ "/usr/bin/mongod", "--quiet", "--bind_ip_all", "--port", "27018", "--replSet", "rs" ] + depends_on: + - mongodb_repl_3 + logging: + driver: none - mongo3: - hostname: mongo3 - container_name: mongo3 - image: mongo + mongodb_repl_3: + container_name: mongodb_repl_3 + image: mongo:4.2.5 restart: always - expose: - - 27017 ports: - - 27020:27017 - command: '--quiet --bind_ip_all --replSet rs0' + - "27020:27018" + entrypoint: [ "/usr/bin/mongod", "--quiet", "--bind_ip_all", "--port", "27018", "--replSet", "rs" ] + logging: + driver: none - mongoreplret: - build: - context: . - dockerfile: MongoReplsetDockerFile + mongo_repl_init: + image: mongo:4.2.5 depends_on: - - mongo1 - - mongo2 - - mongo3 - entrypoint: ["sh", "-c", "mongo-replset-init.sh"] + - mongodb_repl + - mongodb_repl_2 + - mongodb_repl_3 + links: + - mongodb_repl:mongodb_repl + - mongodb_repl_2:mongodb_repl_2 + - mongodb_repl_3:mongodb_repl_3 + environment: + - MONGO1=mongodb_repl + - MONGO2=mongodb_repl_2 + - MONGO3=mongodb_repl_3 + - RS=rs + volumes: + - ./:/scripts + entrypoint: [ "sh", "-c", "/scripts/mongo-repl-init.sh" ] + logging: + driver: none diff --git a/mongo-replset-init.sh b/mongo-replset-init.sh index d5a95b555..9c184d51a 100644 --- a/mongo-replset-init.sh +++ b/mongo-replset-init.sh @@ -1,23 +1,39 @@ #!/bin/bash +mongodb1=`getent hosts ${MONGO1} | awk '{ print $1 }'` -echo "prepare rs initiating" +port=${PORT:-27018} -check_db_status() { - mongo1=$(mongo --host mongo1 --port 27017 --eval "db.stats().ok" | tail -n1 | grep -E '(^|\s)1($|\s)') - mongo2=$(mongo --host mongo2 --port 27017 --eval "db.stats().ok" | tail -n1 | grep -E '(^|\s)1($|\s)') - mongo3=$(mongo --host mongo3 --port 27017 --eval "db.stats().ok" | tail -n1 | grep -E '(^|\s)1($|\s)') - if [[ $mongo1 == 1 ]] && [[ $mongo2 == 1 ]] && [[ $mongo3 == 1 ]]; then - init_rs - else - check_db_status - fi -} +echo "Waiting for startup.." +until mongo --host ${mongodb1}:${port} --eval 'quit(db.runCommand({ ping: 1 }).ok ? 0 : 2)' &>/dev/null; do + printf '.' + sleep 1 +done -init_rs() { - ret=$(mongo --host mongo1 --port 27017 --eval "rs.initiate({ _id: 'rs0', members: [{ _id: 0, host: 'mongo1:27017' }, { _id: 1, host: 'mongo2:27017' }, { _id: 2, host: 'mongo3:27017' } ] })" > /dev/null 2>&1) -} +echo "Started.." -check_db_status > /dev/null 2>&1 - -echo "rs initiating finished" -exit 0 +echo setup.sh time now: `date +"%T" ` +mongo --host ${mongodb1}:${port} <set('database.connections.mongodb2', $config['connections']['mongodb']); $app['config']->set('database.connections.dsn_mongodb', $config['connections']['dsn_mongodb']); $app['config']->set('database.connections.dsn_mongodb_db', $config['connections']['dsn_mongodb_db']); - $app['config']->set('database.connections.mongodb_replset', $config['connections']['mongodb_replset']); + $app['config']->set('database.connections.mongodb_repl', $config['connections']['mongodb_repl']); $app['config']->set('auth.model', 'User'); $app['config']->set('auth.providers.users.model', 'User'); diff --git a/tests/TransactionBuilderTest.php b/tests/TransactionBuilderTest.php index 7b5a31ff4..03b2e6450 100644 --- a/tests/TransactionBuilderTest.php +++ b/tests/TransactionBuilderTest.php @@ -7,7 +7,7 @@ class TransactionBuilderTest extends TestCase { protected $insertData = ['name' => 'klinson', 'age' => 20, 'title' => 'admin']; protected $originData = ['name' => 'users', 'age' => 20, 'title' => 'user']; - protected $connection = 'mongodb_replset'; + protected $connection = 'mongodb_repl'; protected $originConnection = 'mongodb'; public function setUp(): void @@ -22,6 +22,18 @@ public function setUp(): void DB::collection('users')->insert($this->originData); } + protected function getEnvironmentSetUp($app) + { +// if (version_compare(env('MONGO_VERSION'), '4', '<')) { +// $this->markTestSkipped('MongoDB with version below 4 is not supported for transactions'); +// } + + $config = require 'config/database.php'; + + $app['config']->set('database.connections.'.$this->connection, $config['connections'][$this->connection]); + $app['config']->set('database.default', $this->connection); + } + public function tearDown(): void { DB::collection('users')->truncate(); diff --git a/tests/TransactionTest.php b/tests/TransactionTest.php index 6fa615aca..e286016e7 100644 --- a/tests/TransactionTest.php +++ b/tests/TransactionTest.php @@ -7,25 +7,32 @@ class TransactionTest extends TestCase { protected $insertData = ['name' => 'klinson', 'age' => 20, 'title' => 'admin']; protected $originData = ['name' => 'users', 'age' => 20, 'title' => 'user']; - protected $connection = 'mongodb_replset'; + protected $connection = 'mongodb_repl'; protected $originConnection = 'mongodb'; public function setUp(): void { parent::setUp(); - /** change connection to seplset? because the transaction needs */ - $this->originConnection = DB::getDefaultConnection(); - DB::setDefaultConnection($this->connection); + User::on($this->connection)->truncate(); + User::on($this->connection)->create($this->originData); + } - User::truncate(); - User::create($this->originData); + protected function getEnvironmentSetUp($app) + { +// if (version_compare(env('MONGO_VERSION'), '4', '<')) { +// $this->markTestSkipped('MongoDB with version below 4 is not supported for transactions'); +// } + + $config = require 'config/database.php'; + + $app['config']->set('database.connections.'.$this->connection, $config['connections'][$this->connection]); + $app['config']->set('database.default', $this->connection); } public function tearDown(): void { - User::truncate(); - DB::setDefaultConnection($this->originConnection); + User::on($this->connection)->truncate(); parent::tearDown(); } @@ -34,24 +41,24 @@ public function testCreate() { /** rollback test */ DB::beginTransaction(); - $user = User::create($this->insertData); + $user = User::on($this->connection)->create($this->insertData); DB::rollBack(); $this->assertInstanceOf(\Jenssegers\Mongodb\Eloquent\Model::class, $user); $this->assertTrue($user->exists); $this->assertEquals($this->insertData['name'], $user->name); - $check = User::find($user->_id); + $check = User::on($this->connection)->find($user->_id); $this->assertNull($check); /** commit test */ DB::beginTransaction(); - $user = User::create($this->insertData); + $user = User::on($this->connection)->create($this->insertData); DB::commit(); $this->assertInstanceOf(\Jenssegers\Mongodb\Eloquent\Model::class, $user); $this->assertTrue($user->exists); $this->assertEquals($this->insertData['name'], $user->name); - $check = User::find($user->_id); + $check = User::on($this->connection)->find($user->_id); $this->assertNotNull($check); $this->assertEquals($user->name, $check->name); } @@ -61,6 +68,7 @@ public function testInsert() /** rollback test */ DB::beginTransaction(); $user = new User; + $user->on($this->connection); $user->name = $this->insertData['name']; $user->title = $this->insertData['title']; $user->age = $this->insertData['age']; @@ -71,12 +79,13 @@ public function testInsert() $this->assertTrue(isset($user->_id)); $this->assertIsString($user->_id); - $check = User::find($user->_id); + $check = User::on($this->connection)->find($user->_id); $this->assertNull($check); /** commit test */ DB::beginTransaction(); $user = new User; + $user->on($this->connection); $user->name = $this->insertData['name']; $user->title = $this->insertData['title']; $user->age = $this->insertData['age']; @@ -87,7 +96,7 @@ public function testInsert() $this->assertTrue(isset($user->_id)); $this->assertIsString($user->_id); - $check = User::find($user->_id); + $check = User::on($this->connection)->find($user->_id); $this->assertNotNull($check); $this->assertEquals($check->name, $user->name); $this->assertEquals($check->age, $user->age); @@ -97,12 +106,13 @@ public function testInsert() public function testInsertWithId(): void { $id = 1; - $check = User::find($id); + $check = User::on($this->connection)->find($id); $this->assertNull($check); /** rollback test */ DB::beginTransaction(); $user = new User; + $user->on($this->connection); $user->_id = $id; $user->name = $this->insertData['name']; $user->title = $this->insertData['title']; @@ -112,12 +122,13 @@ public function testInsertWithId(): void $this->assertTrue($user->exists); $this->assertEquals($id, $user->_id); - $check = User::find($id); + $check = User::on($this->connection)->find($id); $this->assertNull($check); /** commit test */ DB::beginTransaction(); $user = new User; + $user->on($this->connection); $user->_id = $id; $user->name = $this->insertData['name']; $user->title = $this->insertData['title']; @@ -127,7 +138,7 @@ public function testInsertWithId(): void $this->assertTrue($user->exists); $this->assertEquals($id, $user->_id); - $check = User::find($id); + $check = User::on($this->connection)->find($id); $this->assertNotNull($check); $this->assertEquals($check->name, $user->name); $this->assertEquals($check->age, $user->age); @@ -138,8 +149,8 @@ public function testUpdate() { /** rollback test */ $new_age = $this->insertData['age'] + 1; - $user1 = User::create($this->insertData); - $user2 = User::create($this->insertData); + $user1 = User::on($this->connection)->create($this->insertData); + $user2 = User::on($this->connection)->create($this->insertData); DB::beginTransaction(); $user1->age = $new_age; $user1->save(); @@ -148,15 +159,15 @@ public function testUpdate() $this->assertEquals($new_age, $user1->age); $this->assertEquals($new_age, $user2->age); - $check1 = User::find($user1->_id); - $check2 = User::find($user2->_id); + $check1 = User::on($this->connection)->find($user1->_id); + $check2 = User::on($this->connection)->find($user2->_id); $this->assertEquals($this->insertData['age'], $check1->age); $this->assertEquals($this->insertData['age'], $check2->age); /** commit test */ User::truncate(); - $user1 = User::create($this->insertData); - $user2 = User::create($this->insertData); + $user1 = User::on($this->connection)->create($this->insertData); + $user2 = User::on($this->connection)->create($this->insertData); DB::beginTransaction(); $user1->age = $new_age; $user1->save(); @@ -165,8 +176,8 @@ public function testUpdate() $this->assertEquals($new_age, $user1->age); $this->assertEquals($new_age, $user2->age); - $check1 = User::find($user1->_id); - $check2 = User::find($user2->_id); + $check1 = User::on($this->connection)->find($user1->_id); + $check2 = User::on($this->connection)->find($user2->_id); $this->assertEquals($new_age, $check1->age); $this->assertEquals($new_age, $check2->age); } @@ -174,47 +185,47 @@ public function testUpdate() public function testDelete() { /** rollback test */ - $user1 = User::create($this->insertData); - $user2 = User::create($this->insertData); + $user1 = User::on($this->connection)->create($this->insertData); + $user2 = User::on($this->connection)->create($this->insertData); DB::beginTransaction(); $user1->delete(); - User::destroy((string) $user2->_id); + User::on($this->connection)->destroy((string) $user2->_id); DB::rollBack(); - $check1 = User::find($user1->_id); - $check2 = User::find($user2->_id); + $check1 = User::on($this->connection)->find($user1->_id); + $check2 = User::on($this->connection)->find($user2->_id); $this->assertNotNull($check1); $this->assertNotNull($check2); /** commit test */ User::truncate(); - $user1 = User::create($this->insertData); - $user2 = User::create($this->insertData); + $user1 = User::on($this->connection)->create($this->insertData); + $user2 = User::on($this->connection)->create($this->insertData); DB::beginTransaction(); $user1->delete(); - User::destroy((string) $user2->_id); + User::on($this->connection)->destroy((string) $user2->_id); DB::commit(); - $check1 = User::find($user1->_id); - $check2 = User::find($user2->_id); + $check1 = User::on($this->connection)->find($user1->_id); + $check2 = User::on($this->connection)->find($user2->_id); $this->assertNull($check1); $this->assertNull($check2); } public function testTransaction() { - $count = User::count(); + $count = User::on($this->connection)->count(); $this->assertEquals(1, $count); $new_age = $this->originData['age'] + 1; DB::transaction(function () use ($new_age) { - User::create($this->insertData); - User::where($this->originData['name'])->update(['age' => $new_age]); + User::on($this->connection)->create($this->insertData); + User::on($this->connection)->where($this->originData['name'])->update(['age' => $new_age]); }); - $count = User::count(); + $count = User::on($this->connection)->count(); $this->assertEquals(2, $count); - $checkInsert = User::where($this->insertData['name'])->first(); + $checkInsert = User::on($this->connection)->where($this->insertData['name'])->first(); $this->assertNotNull($checkInsert); - $checkUpdate = User::where($this->originData['name'])->first(); + $checkUpdate = User::on($this->connection)->where($this->originData['name'])->first(); $this->assertEquals($new_age, $checkUpdate->age); } } diff --git a/tests/config/database.php b/tests/config/database.php index 1fdff2880..1a61d855c 100644 --- a/tests/config/database.php +++ b/tests/config/database.php @@ -1,7 +1,9 @@ env('MONGO_DATABASE', 'unittest'), ], - 'mongodb_replset' => [ - 'driver' => 'mongodb', - 'host' => [ - 'mongo1:27017', - 'mongo2:27017', - 'mongo3:27017', + 'mongodb_repl' => [ + 'name' => 'mongodb_repl', + 'driver' => 'mongodb', + 'host' => $mongoReplHost, + 'port' => $mongoReplPort, + 'database' => env('MONGO_DATABASE', 'unittest'), + 'options' => [ + 'replicaSet' => 'rs', + 'serverSelectionTryOnce' => false, ], - 'database' => env('MONGO_DATABASE', 'unittest'), - 'options' => [ - 'replicaSet' => 'rs0', - 'serverSelectionTryOnce' => false, - ] ], 'dsn_mongodb' => [ diff --git a/tests/models/User.php b/tests/models/User.php index 56cee1636..1217af762 100644 --- a/tests/models/User.php +++ b/tests/models/User.php @@ -23,7 +23,7 @@ class User extends Eloquent implements AuthenticatableContract, CanResetPassword { use Authenticatable, CanResetPassword, HybridRelations, Notifiable; -// protected $connection = 'mongodb'; + protected $connection = 'mongodb'; protected $dates = ['birthday', 'entry.date']; protected static $unguarded = true; From add9516d69a7619eaf241d5b81f5a202a0dd8be9 Mon Sep 17 00:00:00 2001 From: klinson Date: Tue, 21 Jul 2020 15:05:36 +0800 Subject: [PATCH 20/37] update tests configs --- tests/TransactionBuilderTest.php | 6 +++--- tests/TransactionTest.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/TransactionBuilderTest.php b/tests/TransactionBuilderTest.php index 03b2e6450..eba7a5a93 100644 --- a/tests/TransactionBuilderTest.php +++ b/tests/TransactionBuilderTest.php @@ -24,9 +24,9 @@ public function setUp(): void protected function getEnvironmentSetUp($app) { -// if (version_compare(env('MONGO_VERSION'), '4', '<')) { -// $this->markTestSkipped('MongoDB with version below 4 is not supported for transactions'); -// } + if (version_compare(env('MONGO_VERSION'), '4', '<')) { + $this->markTestSkipped('MongoDB with version below 4 is not supported for transactions'); + } $config = require 'config/database.php'; diff --git a/tests/TransactionTest.php b/tests/TransactionTest.php index e286016e7..7f6c83b90 100644 --- a/tests/TransactionTest.php +++ b/tests/TransactionTest.php @@ -20,9 +20,9 @@ public function setUp(): void protected function getEnvironmentSetUp($app) { -// if (version_compare(env('MONGO_VERSION'), '4', '<')) { -// $this->markTestSkipped('MongoDB with version below 4 is not supported for transactions'); -// } + if (version_compare(env('MONGO_VERSION'), '4', '<')) { + $this->markTestSkipped('MongoDB with version below 4 is not supported for transactions'); + } $config = require 'config/database.php'; From 14b3ad7534f3cd4dd8d64e55f8cebfa56a2e5414 Mon Sep 17 00:00:00 2001 From: klinson Date: Tue, 21 Jul 2020 15:18:13 +0800 Subject: [PATCH 21/37] update tests configs --- tests/TransactionBuilderTest.php | 4 ---- tests/TransactionTest.php | 4 ---- 2 files changed, 8 deletions(-) diff --git a/tests/TransactionBuilderTest.php b/tests/TransactionBuilderTest.php index eba7a5a93..609bef72d 100644 --- a/tests/TransactionBuilderTest.php +++ b/tests/TransactionBuilderTest.php @@ -24,10 +24,6 @@ public function setUp(): void protected function getEnvironmentSetUp($app) { - if (version_compare(env('MONGO_VERSION'), '4', '<')) { - $this->markTestSkipped('MongoDB with version below 4 is not supported for transactions'); - } - $config = require 'config/database.php'; $app['config']->set('database.connections.'.$this->connection, $config['connections'][$this->connection]); diff --git a/tests/TransactionTest.php b/tests/TransactionTest.php index 7f6c83b90..69af2c3cd 100644 --- a/tests/TransactionTest.php +++ b/tests/TransactionTest.php @@ -20,10 +20,6 @@ public function setUp(): void protected function getEnvironmentSetUp($app) { - if (version_compare(env('MONGO_VERSION'), '4', '<')) { - $this->markTestSkipped('MongoDB with version below 4 is not supported for transactions'); - } - $config = require 'config/database.php'; $app['config']->set('database.connections.'.$this->connection, $config['connections'][$this->connection]); From 0c22e4a34e8fd61397533af239fddf789b3ec82f Mon Sep 17 00:00:00 2001 From: klinson Date: Tue, 21 Jul 2020 15:45:19 +0800 Subject: [PATCH 22/37] update ci.yml --- .github/workflows/build-ci.yml | 27 ++++++++++++++++----------- phpunit.xml.dist | 1 + 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build-ci.yml b/.github/workflows/build-ci.yml index e830b6569..e2ff26b47 100644 --- a/.github/workflows/build-ci.yml +++ b/.github/workflows/build-ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ${{matrix.os}} strategy: matrix: - php: ['7.2', '7.3', '7.4'] + php: ['7.1', '7.2', '7.3', '7.4'] os: ['ubuntu-latest'] mongodb: ['3.6', '4.0', '4.2'] services: @@ -28,18 +28,21 @@ jobs: MYSQL_DATABASE: 'unittest' MYSQL_ROOT_PASSWORD: name: PHP v${{ matrix.php }} with Mongo v${{ matrix.mongodb }} - steps: - - uses: actions/checkout@v2 - - name: "Installing php" - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - extensions: curl,mbstring,xdebug - coverage: xdebug - tools: composer + - uses: actions/checkout@v1 + - name: Creating MongoDB replica + if: matrix.mongodb == '4.0' || matrix.mongodb == '4.2' + run: | + docker run --name mongodb_repl -e MONGO_INITDB_DATABASE=unittest --publish 27018:27018 --detach mongo:${{ matrix.mongodb }} mongod --port 27018 --replSet rs + until docker exec --tty mongodb_repl mongo 127.0.0.1:27018 --eval "db.serverStatus()"; do + sleep 1 + done + sudo docker exec --tty mongodb_repl mongo 127.0.0.1:27018 --eval "rs.initiate({\"_id\":\"rs\",\"members\":[{\"_id\":0,\"host\":\"127.0.0.1:27018\" }]})" + env: + MONGO_HOST: 0.0.0.0 + MONGO_REPL_HOST: 0.0.0.0 - name: Show PHP version - run: php -v && composer -V + run: php${{ matrix.php }} -v && composer -V - name: Show Docker version run: if [[ "$DEBUG" == "true" ]]; then docker version && env; fi env: @@ -60,7 +63,9 @@ jobs: run: | ./vendor/bin/phpunit --coverage-clover coverage.xml env: + MONGO_VERSION: ${{ matrix.mongodb }}) MONGO_HOST: 0.0.0.0 + MONGO_REPL_HOST: 0.0.0.0 MYSQL_HOST: 0.0.0.0 MYSQL_PORT: 3307 - name: Send coveralls diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 51f570dfb..4174328b5 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -51,6 +51,7 @@ + From 0b840db9e45e85f827cd79e0684b80585a75f647 Mon Sep 17 00:00:00 2001 From: klinson Date: Tue, 21 Jul 2020 16:03:17 +0800 Subject: [PATCH 23/37] update tests --- tests/TransactionTest.php | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/TransactionTest.php b/tests/TransactionTest.php index 69af2c3cd..8726fc623 100644 --- a/tests/TransactionTest.php +++ b/tests/TransactionTest.php @@ -8,7 +8,6 @@ class TransactionTest extends TestCase protected $insertData = ['name' => 'klinson', 'age' => 20, 'title' => 'admin']; protected $originData = ['name' => 'users', 'age' => 20, 'title' => 'user']; protected $connection = 'mongodb_repl'; - protected $originConnection = 'mongodb'; public function setUp(): void { @@ -63,8 +62,7 @@ public function testInsert() { /** rollback test */ DB::beginTransaction(); - $user = new User; - $user->on($this->connection); + $user = User::on($this->connection)->getModel(); $user->name = $this->insertData['name']; $user->title = $this->insertData['title']; $user->age = $this->insertData['age']; @@ -80,8 +78,7 @@ public function testInsert() /** commit test */ DB::beginTransaction(); - $user = new User; - $user->on($this->connection); + $user = User::on($this->connection)->getModel(); $user->name = $this->insertData['name']; $user->title = $this->insertData['title']; $user->age = $this->insertData['age']; @@ -107,8 +104,7 @@ public function testInsertWithId(): void /** rollback test */ DB::beginTransaction(); - $user = new User; - $user->on($this->connection); + $user = User::on($this->connection)->getModel(); $user->_id = $id; $user->name = $this->insertData['name']; $user->title = $this->insertData['title']; @@ -123,8 +119,7 @@ public function testInsertWithId(): void /** commit test */ DB::beginTransaction(); - $user = new User; - $user->on($this->connection); + $user = User::on($this->connection)->getModel(); $user->_id = $id; $user->name = $this->insertData['name']; $user->title = $this->insertData['title']; From cf88a035b52088dab61a6f352bcdcdee3e11c6f6 Mon Sep 17 00:00:00 2001 From: klinson Date: Tue, 21 Jul 2020 16:11:39 +0800 Subject: [PATCH 24/37] update tests --- tests/TransactionTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/TransactionTest.php b/tests/TransactionTest.php index 8726fc623..f2b38809b 100644 --- a/tests/TransactionTest.php +++ b/tests/TransactionTest.php @@ -156,7 +156,7 @@ public function testUpdate() $this->assertEquals($this->insertData['age'], $check2->age); /** commit test */ - User::truncate(); + User::on($this->connection)->truncate(); $user1 = User::on($this->connection)->create($this->insertData); $user2 = User::on($this->connection)->create($this->insertData); DB::beginTransaction(); @@ -188,7 +188,7 @@ public function testDelete() $this->assertNotNull($check2); /** commit test */ - User::truncate(); + User::on($this->connection)->truncate(); $user1 = User::on($this->connection)->create($this->insertData); $user2 = User::on($this->connection)->create($this->insertData); DB::beginTransaction(); From 2664bd5a879073c6cd45f64919265ba3c604339a Mon Sep 17 00:00:00 2001 From: klinson Date: Tue, 21 Jul 2020 16:46:16 +0800 Subject: [PATCH 25/37] update tests --- tests/TransactionTest.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/TransactionTest.php b/tests/TransactionTest.php index f2b38809b..cacf3c2ef 100644 --- a/tests/TransactionTest.php +++ b/tests/TransactionTest.php @@ -177,28 +177,20 @@ public function testDelete() { /** rollback test */ $user1 = User::on($this->connection)->create($this->insertData); - $user2 = User::on($this->connection)->create($this->insertData); DB::beginTransaction(); $user1->delete(); - User::on($this->connection)->destroy((string) $user2->_id); DB::rollBack(); $check1 = User::on($this->connection)->find($user1->_id); - $check2 = User::on($this->connection)->find($user2->_id); $this->assertNotNull($check1); - $this->assertNotNull($check2); /** commit test */ User::on($this->connection)->truncate(); $user1 = User::on($this->connection)->create($this->insertData); - $user2 = User::on($this->connection)->create($this->insertData); DB::beginTransaction(); $user1->delete(); - User::on($this->connection)->destroy((string) $user2->_id); DB::commit(); $check1 = User::on($this->connection)->find($user1->_id); - $check2 = User::on($this->connection)->find($user2->_id); $this->assertNull($check1); - $this->assertNull($check2); } public function testTransaction() From 44bd0817bc3b9da7a9c7de25ab0b4530a84b4de9 Mon Sep 17 00:00:00 2001 From: klinson Date: Tue, 21 Jul 2020 17:31:07 +0800 Subject: [PATCH 26/37] update tests --- tests/TransactionBuilderTest.php | 4 ++++ tests/TransactionTest.php | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/tests/TransactionBuilderTest.php b/tests/TransactionBuilderTest.php index 609bef72d..eba7a5a93 100644 --- a/tests/TransactionBuilderTest.php +++ b/tests/TransactionBuilderTest.php @@ -24,6 +24,10 @@ public function setUp(): void protected function getEnvironmentSetUp($app) { + if (version_compare(env('MONGO_VERSION'), '4', '<')) { + $this->markTestSkipped('MongoDB with version below 4 is not supported for transactions'); + } + $config = require 'config/database.php'; $app['config']->set('database.connections.'.$this->connection, $config['connections'][$this->connection]); diff --git a/tests/TransactionTest.php b/tests/TransactionTest.php index cacf3c2ef..0cb95ddaf 100644 --- a/tests/TransactionTest.php +++ b/tests/TransactionTest.php @@ -19,6 +19,10 @@ public function setUp(): void protected function getEnvironmentSetUp($app) { + if (version_compare(env('MONGO_VERSION'), '4', '<')) { + $this->markTestSkipped('MongoDB with version below 4 is not supported for transactions'); + } + $config = require 'config/database.php'; $app['config']->set('database.connections.'.$this->connection, $config['connections'][$this->connection]); From 83f45c991970fc679c97862a7261fdef607c8312 Mon Sep 17 00:00:00 2001 From: klinson Date: Thu, 23 Jul 2020 09:58:01 +0800 Subject: [PATCH 27/37] delete links of docker-compose.yaml remove support for php 7.1 --- .github/workflows/build-ci.yml | 2 +- docker-compose.yml | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/build-ci.yml b/.github/workflows/build-ci.yml index e2ff26b47..849243b1b 100644 --- a/.github/workflows/build-ci.yml +++ b/.github/workflows/build-ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ${{matrix.os}} strategy: matrix: - php: ['7.1', '7.2', '7.3', '7.4'] + php: ['7.2', '7.3', '7.4'] os: ['ubuntu-latest'] mongodb: ['3.6', '4.0', '4.2'] services: diff --git a/docker-compose.yml b/docker-compose.yml index 0057eea30..51c21e948 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -47,9 +47,6 @@ services: depends_on: - mongodb_repl_2 - mongodb_repl_3 - links: - - mongodb_repl_2:mongodb_repl_2 - - mongodb_repl_3:mongodb_repl_3 logging: driver: none @@ -81,10 +78,6 @@ services: - mongodb_repl - mongodb_repl_2 - mongodb_repl_3 - links: - - mongodb_repl:mongodb_repl - - mongodb_repl_2:mongodb_repl_2 - - mongodb_repl_3:mongodb_repl_3 environment: - MONGO1=mongodb_repl - MONGO2=mongodb_repl_2 From 7741acbefde675224e0416eea25f717b59623212 Mon Sep 17 00:00:00 2001 From: klinson Date: Thu, 23 Jul 2020 14:47:49 +0800 Subject: [PATCH 28/37] optimize code --- src/Jenssegers/Mongodb/Query/Builder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Jenssegers/Mongodb/Query/Builder.php b/src/Jenssegers/Mongodb/Query/Builder.php index 5fd02f6f2..db7e6786e 100644 --- a/src/Jenssegers/Mongodb/Query/Builder.php +++ b/src/Jenssegers/Mongodb/Query/Builder.php @@ -1227,7 +1227,7 @@ public function options(array $options) */ protected function setSession($options) { - if ($session = $this->connection->getSession()) { + if (!isset($options['session']) && ($session = $this->connection->getSession())) { $options['session'] = $session; } return $options; From dafee61858c0c3e05e81784ef76fab987d8c5b9e Mon Sep 17 00:00:00 2001 From: klinson Date: Fri, 20 Nov 2020 17:49:29 +0800 Subject: [PATCH 29/37] remove testInsertWithId --- tests/TransactionTest.php | 40 --------------------------------------- 1 file changed, 40 deletions(-) diff --git a/tests/TransactionTest.php b/tests/TransactionTest.php index 0cb95ddaf..597c6032d 100644 --- a/tests/TransactionTest.php +++ b/tests/TransactionTest.php @@ -100,46 +100,6 @@ public function testInsert() $this->assertEquals($check->title, $user->title); } - public function testInsertWithId(): void - { - $id = 1; - $check = User::on($this->connection)->find($id); - $this->assertNull($check); - - /** rollback test */ - DB::beginTransaction(); - $user = User::on($this->connection)->getModel(); - $user->_id = $id; - $user->name = $this->insertData['name']; - $user->title = $this->insertData['title']; - $user->age = $this->insertData['age']; - $user->save(); - DB::rollBack(); - - $this->assertTrue($user->exists); - $this->assertEquals($id, $user->_id); - $check = User::on($this->connection)->find($id); - $this->assertNull($check); - - /** commit test */ - DB::beginTransaction(); - $user = User::on($this->connection)->getModel(); - $user->_id = $id; - $user->name = $this->insertData['name']; - $user->title = $this->insertData['title']; - $user->age = $this->insertData['age']; - $user->save(); - DB::commit(); - - $this->assertTrue($user->exists); - $this->assertEquals($id, $user->_id); - $check = User::on($this->connection)->find($id); - $this->assertNotNull($check); - $this->assertEquals($check->name, $user->name); - $this->assertEquals($check->age, $user->age); - $this->assertEquals($check->title, $user->title); - } - public function testUpdate() { /** rollback test */ From 0fd27bac4a92aa6e329b148e6204aee540134bda Mon Sep 17 00:00:00 2001 From: klinson Date: Mon, 23 Nov 2020 10:07:33 +0800 Subject: [PATCH 30/37] update build-ci.yml --- .github/workflows/build-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-ci.yml b/.github/workflows/build-ci.yml index 180ed7cde..7a49a35dd 100644 --- a/.github/workflows/build-ci.yml +++ b/.github/workflows/build-ci.yml @@ -42,7 +42,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: Creating MongoDB replica - if: matrix.mongodb == '4.0' || matrix.mongodb == '4.2' + if: matrix.mongodb == '4.0' || matrix.mongodb == '4.2' || matrix.mongodb == '4.4' run: | docker run --name mongodb_repl -e MONGO_INITDB_DATABASE=unittest --publish 27018:27018 --detach mongo:${{ matrix.mongodb }} mongod --port 27018 --replSet rs until docker exec --tty mongodb_repl mongo 127.0.0.1:27018 --eval "db.serverStatus()"; do From 6e89c8b0dbfad661325a7eedd7575e4884771259 Mon Sep 17 00:00:00 2001 From: klinson Date: Mon, 23 Nov 2020 11:12:04 +0800 Subject: [PATCH 31/37] add return info to phpdoc --- src/Jenssegers/Mongodb/Connection.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Jenssegers/Mongodb/Connection.php b/src/Jenssegers/Mongodb/Connection.php index e9551935a..c3764e657 100644 --- a/src/Jenssegers/Mongodb/Connection.php +++ b/src/Jenssegers/Mongodb/Connection.php @@ -292,6 +292,7 @@ public function __call($method, $parameters) * To use transactions on MongoDB 4.2 deployments(replica sets and sharded clusters), clients must use MongoDB drivers updated for MongoDB 4.2. * * @see https://docs.mongodb.com/manual/core/transactions/ + * @return void */ public function beginTransaction() { @@ -307,6 +308,7 @@ public function beginTransaction() /** * commit transaction in this session and close this session + * @return void */ public function commit() { @@ -318,6 +320,7 @@ public function commit() /** * rollback transaction in this session and close this session + * @return void */ public function rollBack($toLevel = null) { @@ -330,6 +333,7 @@ public function rollBack($toLevel = null) /** * close this session and get last session key to session_key * Why do it ? Because nested transactions + * @return void */ protected function setLastSession() { From 5645fc7f202050a95d9c3a60acb340d781280907 Mon Sep 17 00:00:00 2001 From: klinson Date: Fri, 19 Feb 2021 17:37:19 +0800 Subject: [PATCH 32/37] format code --- src/Jenssegers/Mongodb/Connection.php | 8 ++++++++ src/Jenssegers/Mongodb/Query/Builder.php | 13 ++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Jenssegers/Mongodb/Connection.php b/src/Jenssegers/Mongodb/Connection.php index c3764e657..641eb80c2 100644 --- a/src/Jenssegers/Mongodb/Connection.php +++ b/src/Jenssegers/Mongodb/Connection.php @@ -24,7 +24,15 @@ class Connection extends BaseConnection */ protected $connection; + /** + * A random unique id for identification of transaction. + * @var string + */ protected $session_key; + /** + * A list of transaction sessions. + * @var array + */ protected $sessions = []; /** diff --git a/src/Jenssegers/Mongodb/Query/Builder.php b/src/Jenssegers/Mongodb/Query/Builder.php index 0f83568f8..4e22620bd 100644 --- a/src/Jenssegers/Mongodb/Query/Builder.php +++ b/src/Jenssegers/Mongodb/Query/Builder.php @@ -728,9 +728,8 @@ public function from($collection, $as = null) */ public function truncate(): bool { - $options = []; - // if transaction in session - $options = $this->setSession($options); + // Check if transaction exist in session + $options = $this->setSession(); $result = $this->collection->deleteMany($options); @@ -860,7 +859,7 @@ protected function performUpdate($query, array $options = []) $options['multiple'] = true; } - // if transaction in session + // Check if transaction exist in session $options = $this->setSession($options); $wheres = $this->compileWheres(); @@ -1196,14 +1195,14 @@ public function options(array $options) } /** - * set session for the transaction + * Set session for the transaction * @param $session * @return mixed */ - protected function setSession($options) + protected function setSession($options = []) { if (!isset($options['session']) && ($session = $this->connection->getSession())) { - $options['session'] = $session; + $options['session'] = $session; } return $options; } From 9cd8bb2708d5de3acfaf4933aa035aeec8691135 Mon Sep 17 00:00:00 2001 From: klinson Date: Fri, 19 Feb 2021 17:37:34 +0800 Subject: [PATCH 33/37] update README.md --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index d5cb58b07..e48daa4c8 100644 --- a/README.md +++ b/README.md @@ -963,26 +963,26 @@ To see the available operations, check the [Eloquent](#eloquent) section. Transaction ------- -Transaction requires mongodb version V4.0 or more and deployment replica sets or sharded clusters.You can look at its speciality [in the MongoDB docs](https://docs.mongodb.com/manual/core/transactions/) +Transaction requires MongoDB version ^4.0 as well as deployment of replica set or sharded clusters. You can find more information [in the MongoDB docs](https://docs.mongodb.com/manual/core/transactions/) ### Basic Usage -Transaction supports create/insert,update,delete,etc operation. +Transaction supports CREATE/INSERT/UPDATE/DELETE operations. ```php DB::transaction(function () { - User::create(['name' => 'klinson', 'age' => 19, 'title' => 'admin', 'email' => 'klinsonup@gmail.com']); - DB::collection('users')->where('name', 'klinson')->update(['age' => 20]); - DB::collection('users')->where('name', 'klinson')->delete(); + User::create(['name' => 'john', 'age' => 19, 'title' => 'admin', 'email' => 'klinsonup@gmail.com']); + DB::collection('users')->where('name', 'john')->update(['age' => 20]); + DB::collection('users')->where('name', 'john')->delete(); }); ``` ```php // begin a transaction DB::beginTransaction(); -User::create(['name' => 'klinson', 'age' => 19, 'title' => 'admin', 'email' => 'klinsonup@gmail.com']); -DB::collection('users')->where('name', 'klinson')->update(['age' => 20]); -DB::collection('users')->where('name', 'klinson')->delete(); +User::create(['name' => 'john', 'age' => 19, 'title' => 'admin', 'email' => 'klinsonup@gmail.com']); +DB::collection('users')->where('name', 'john')->update(['age' => 20]); +DB::collection('users')->where('name', 'john')->delete(); // you can commit your changes DB::commit(); @@ -991,12 +991,12 @@ DB::commit(); //DB::rollBack(); ``` -Transaction supports infinite-level nested transactions, but outside transaction rollbacks do not affect the commit of inside transactions. +**NOTE:** Transaction supports infinite-level of nested transactions, but outside transaction rollbacks do not affect the commits of inside transactions. ```php DB::beginTransaction(); -User::create(['name' => 'klinson', 'age' => 20, 'title' => 'admin']); +User::create(['name' => 'john', 'age' => 20, 'title' => 'admin']); DB::transaction(function () { - DB::collection('users')->where('name', 'klinson')->update(['age' => 20]); + DB::collection('users')->where('name', 'john')->update(['age' => 20]); }); DB::rollBack(); ``` From 49307e217fba64f7d1b82408097aedc4bbeb4948 Mon Sep 17 00:00:00 2001 From: klinson Date: Sat, 27 Mar 2021 10:42:53 +0800 Subject: [PATCH 34/37] remove excess $option --- src/Jenssegers/Mongodb/Query/Builder.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Jenssegers/Mongodb/Query/Builder.php b/src/Jenssegers/Mongodb/Query/Builder.php index 4e22620bd..0f7cce2ce 100644 --- a/src/Jenssegers/Mongodb/Query/Builder.php +++ b/src/Jenssegers/Mongodb/Query/Builder.php @@ -572,10 +572,8 @@ public function insert(array $values) $values = [$values]; } - // Batch insert - $options = []; // if transaction in session - $options = $this->setSession($options); + $options = $this->setSession(); $result = $this->collection->insertMany($values, $options); @@ -587,9 +585,8 @@ public function insert(array $values) */ public function insertGetId(array $values, $sequence = null) { - $options = []; // if transaction in session - $options = $this->setSession($options); + $options = $this->setSession(); $result = $this->collection->insertOne($values, $options); @@ -699,9 +696,8 @@ public function delete($id = null) $wheres = $this->compileWheres(); - $options = []; // if transaction in session - $options = $this->setSession($options); + $options = $this->setSession(); $result = $this->collection->DeleteMany($wheres, $options); if (1 == (int) $result->isAcknowledged()) { From 59020fbe88100f2f0d42e61216b3447d5d212f9d Mon Sep 17 00:00:00 2001 From: klinson Date: Sat, 27 Mar 2021 12:54:10 +0800 Subject: [PATCH 35/37] divide testUpdate on two methods testUpdateWithRollback and testUpdateWithCommit --- tests/TransactionTest.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/TransactionTest.php b/tests/TransactionTest.php index 597c6032d..b9ad78bf2 100644 --- a/tests/TransactionTest.php +++ b/tests/TransactionTest.php @@ -100,7 +100,7 @@ public function testInsert() $this->assertEquals($check->title, $user->title); } - public function testUpdate() + public function testUpdateWithRollback () { /** rollback test */ $new_age = $this->insertData['age'] + 1; @@ -108,7 +108,7 @@ public function testUpdate() $user2 = User::on($this->connection)->create($this->insertData); DB::beginTransaction(); $user1->age = $new_age; - $user1->save(); + $user1->update(); $user2->update(['age' => $new_age]); DB::rollBack(); $this->assertEquals($new_age, $user1->age); @@ -118,6 +118,11 @@ public function testUpdate() $check2 = User::on($this->connection)->find($user2->_id); $this->assertEquals($this->insertData['age'], $check1->age); $this->assertEquals($this->insertData['age'], $check2->age); + } + + public function testUpdateWithCommit() + { + $new_age = $this->insertData['age'] + 1; /** commit test */ User::on($this->connection)->truncate(); @@ -125,7 +130,7 @@ public function testUpdate() $user2 = User::on($this->connection)->create($this->insertData); DB::beginTransaction(); $user1->age = $new_age; - $user1->save(); + $user1->update(); $user2->update(['age' => $new_age]); DB::commit(); $this->assertEquals($new_age, $user1->age); From 97f9b4bf24b3dfc870934c37f6950ea1835136a5 Mon Sep 17 00:00:00 2001 From: klinson Date: Sat, 27 Mar 2021 13:01:48 +0800 Subject: [PATCH 36/37] update ci part --- .github/workflows/build-ci.yml | 126 +++++++++++++++++---------------- 1 file changed, 66 insertions(+), 60 deletions(-) diff --git a/.github/workflows/build-ci.yml b/.github/workflows/build-ci.yml index fb4472ce7..12257f48d 100644 --- a/.github/workflows/build-ci.yml +++ b/.github/workflows/build-ci.yml @@ -14,19 +14,19 @@ jobs: strategy: matrix: include: - - { os: ubuntu-latest, php: 7.2, mongodb: 3.6, experimental: true} - - { os: ubuntu-latest, php: 7.2, mongodb: '4.0', experimental: true} - - { os: ubuntu-latest, php: 7.2, mongodb: 4.2, experimental: true} - - { os: ubuntu-latest, php: 7.2, mongodb: 4.4, experimental: true} - - { os: ubuntu-latest, php: 7.3, mongodb: 3.6, experimental: false} - - { os: ubuntu-latest, php: 7.3, mongodb: '4.0', experimental: false} - - { os: ubuntu-latest, php: 7.3, mongodb: 4.2, experimental: false} - - { os: ubuntu-latest, php: 7.3, mongodb: 4.4, experimental: false} - - { os: ubuntu-latest, php: 7.4, mongodb: 3.6, experimental: false} - - { os: ubuntu-latest, php: 7.4, mongodb: '4.0', experimental: false} - - { os: ubuntu-latest, php: 7.4, mongodb: 4.2, experimental: false} - - { os: ubuntu-latest, php: 7.4, mongodb: 4.4, experimental: false} - - { os: ubuntu-latest, php: 8.0, mongodb: 4.4, experimental: false} + - { os: ubuntu-latest, php: 7.2, mongodb: 3.6, experimental: true} + - { os: ubuntu-latest, php: 7.2, mongodb: '4.0', experimental: true} + - { os: ubuntu-latest, php: 7.2, mongodb: 4.2, experimental: true} + - { os: ubuntu-latest, php: 7.2, mongodb: 4.4, experimental: true} + - { os: ubuntu-latest, php: 7.3, mongodb: 3.6, experimental: false} + - { os: ubuntu-latest, php: 7.3, mongodb: '4.0', experimental: false} + - { os: ubuntu-latest, php: 7.3, mongodb: 4.2, experimental: false} + - { os: ubuntu-latest, php: 7.3, mongodb: 4.4, experimental: false} + - { os: ubuntu-latest, php: 7.4, mongodb: 3.6, experimental: false} + - { os: ubuntu-latest, php: 7.4, mongodb: '4.0', experimental: false} + - { os: ubuntu-latest, php: 7.4, mongodb: 4.2, experimental: false} + - { os: ubuntu-latest, php: 7.4, mongodb: 4.4, experimental: false} + - { os: ubuntu-latest, php: 8.0, mongodb: 4.4, experimental: false} services: mongo: image: mongo:${{ matrix.mongodb }} @@ -40,51 +40,57 @@ jobs: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' MYSQL_DATABASE: 'unittest' MYSQL_ROOT_PASSWORD: + steps: - - uses: actions/checkout@v1 - - name: Creating MongoDB replica - if: matrix.mongodb == '4.0' || matrix.mongodb == '4.2' || matrix.mongodb == '4.4' - run: | - docker run --name mongodb_repl -e MONGO_INITDB_DATABASE=unittest --publish 27018:27018 --detach mongo:${{ matrix.mongodb }} mongod --port 27018 --replSet rs - until docker exec --tty mongodb_repl mongo 127.0.0.1:27018 --eval "db.serverStatus()"; do - sleep 1 - done - sudo docker exec --tty mongodb_repl mongo 127.0.0.1:27018 --eval "rs.initiate({\"_id\":\"rs\",\"members\":[{\"_id\":0,\"host\":\"127.0.0.1:27018\" }]})" - env: - MONGO_HOST: 0.0.0.0 - MONGO_REPL_HOST: 0.0.0.0 - - name: Show PHP version - run: php${{ matrix.php }} -v && composer -V - - name: Show Docker version - run: if [[ "$DEBUG" == "true" ]]; then docker version && env; fi - env: - DEBUG: ${{secrets.DEBUG}} - - name: Download Composer cache dependencies from cache - if: (!startsWith(matrix.php, '7.2')) - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache Composer dependencies - if: (!startsWith(matrix.php, '7.2')) - uses: actions/cache@v1 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ matrix.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ matrix.os }}-composer- - - name: Install dependencies - if: (!startsWith(matrix.php, '7.2')) - run: | - composer install --no-interaction - - name: Run tests - if: (!startsWith(matrix.php, '7.2')) - run: | - ./vendor/bin/phpunit --coverage-clover coverage.xml - env: - MONGO_VERSION: ${{ matrix.mongodb }}) - MONGO_HOST: 0.0.0.0 - MONGO_REPL_HOST: 0.0.0.0 - MYSQL_HOST: 0.0.0.0 - MYSQL_PORT: 3307 - - uses: codecov/codecov-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: false + - uses: actions/checkout@v2 + - name: Creating MongoDB replica + if: matrix.mongodb == '4.0' || matrix.mongodb == '4.2' || matrix.mongodb == '4.4' + run: | + docker run --name mongodb_repl -e MONGO_INITDB_DATABASE=unittest --publish 27018:27018 --detach mongo:${{ matrix.mongodb }} mongod --port 27018 --replSet rs + until docker exec --tty mongodb_repl mongo 127.0.0.1:27018 --eval "db.serverStatus()"; do + sleep 1 + done + sudo docker exec --tty mongodb_repl mongo 127.0.0.1:27018 --eval "rs.initiate({\"_id\":\"rs\",\"members\":[{\"_id\":0,\"host\":\"127.0.0.1:27018\" }]})" + env: + MONGO_HOST: 0.0.0.0 + MONGO_REPL_HOST: 0.0.0.0 + - name: "Installing php" + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: curl,mbstring,xdebug + coverage: xdebug + tools: composer + - name: Show PHP version + run: php -v && composer -V + - name: Show Docker version + run: if [[ "$DEBUG" == "true" ]]; then docker version && env; fi + env: + DEBUG: ${{secrets.DEBUG}} + - name: Download Composer cache dependencies from cache + if: (!startsWith(matrix.php, '7.2')) + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + - name: Cache Composer dependencies + if: (!startsWith(matrix.php, '7.2')) + uses: actions/cache@v1 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ matrix.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ matrix.os }}-composer- + - name: Install dependencies + if: (!startsWith(matrix.php, '7.2')) + run: | + composer install --no-interaction + - name: Run tests + if: (!startsWith(matrix.php, '7.2')) + run: | + ./vendor/bin/phpunit --coverage-clover coverage.xml + env: + MONGO_HOST: 0.0.0.0 + MYSQL_HOST: 0.0.0.0 + MYSQL_PORT: 3307 + - uses: codecov/codecov-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: false From 9c90125860a085eaac6487a7bd65556a9bcf363a Mon Sep 17 00:00:00 2001 From: klinson Date: Sat, 27 Mar 2021 13:11:18 +0800 Subject: [PATCH 37/37] update ci part --- .github/workflows/build-ci.yml | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-ci.yml b/.github/workflows/build-ci.yml index 12257f48d..a68c051ca 100644 --- a/.github/workflows/build-ci.yml +++ b/.github/workflows/build-ci.yml @@ -14,19 +14,19 @@ jobs: strategy: matrix: include: - - { os: ubuntu-latest, php: 7.2, mongodb: 3.6, experimental: true} - - { os: ubuntu-latest, php: 7.2, mongodb: '4.0', experimental: true} - - { os: ubuntu-latest, php: 7.2, mongodb: 4.2, experimental: true} - - { os: ubuntu-latest, php: 7.2, mongodb: 4.4, experimental: true} - - { os: ubuntu-latest, php: 7.3, mongodb: 3.6, experimental: false} - - { os: ubuntu-latest, php: 7.3, mongodb: '4.0', experimental: false} - - { os: ubuntu-latest, php: 7.3, mongodb: 4.2, experimental: false} - - { os: ubuntu-latest, php: 7.3, mongodb: 4.4, experimental: false} - - { os: ubuntu-latest, php: 7.4, mongodb: 3.6, experimental: false} - - { os: ubuntu-latest, php: 7.4, mongodb: '4.0', experimental: false} - - { os: ubuntu-latest, php: 7.4, mongodb: 4.2, experimental: false} - - { os: ubuntu-latest, php: 7.4, mongodb: 4.4, experimental: false} - - { os: ubuntu-latest, php: 8.0, mongodb: 4.4, experimental: false} + - { os: ubuntu-latest, php: 7.2, mongodb: 3.6, experimental: true} + - { os: ubuntu-latest, php: 7.2, mongodb: '4.0', experimental: true} + - { os: ubuntu-latest, php: 7.2, mongodb: 4.2, experimental: true} + - { os: ubuntu-latest, php: 7.2, mongodb: 4.4, experimental: true} + - { os: ubuntu-latest, php: 7.3, mongodb: 3.6, experimental: false} + - { os: ubuntu-latest, php: 7.3, mongodb: '4.0', experimental: false} + - { os: ubuntu-latest, php: 7.3, mongodb: 4.2, experimental: false} + - { os: ubuntu-latest, php: 7.3, mongodb: 4.4, experimental: false} + - { os: ubuntu-latest, php: 7.4, mongodb: 3.6, experimental: false} + - { os: ubuntu-latest, php: 7.4, mongodb: '4.0', experimental: false} + - { os: ubuntu-latest, php: 7.4, mongodb: 4.2, experimental: false} + - { os: ubuntu-latest, php: 7.4, mongodb: 4.4, experimental: false} + - { os: ubuntu-latest, php: 8.0, mongodb: 4.4, experimental: false} services: mongo: image: mongo:${{ matrix.mongodb }} @@ -87,7 +87,9 @@ jobs: run: | ./vendor/bin/phpunit --coverage-clover coverage.xml env: + MONGO_VERSION: ${{ matrix.mongodb }}) MONGO_HOST: 0.0.0.0 + MONGO_REPL_HOST: 0.0.0.0 MYSQL_HOST: 0.0.0.0 MYSQL_PORT: 3307 - uses: codecov/codecov-action@v1