Skip to content

Commit 149dc00

Browse files
committed
WithParallelPhyiscalDatabase trait
1 parent a9df3e0 commit 149dc00

File tree

4 files changed

+111
-24
lines changed

4 files changed

+111
-24
lines changed

README.md

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,7 @@ composer require recca0120/laravel-parallel
2121

2222
## Usage
2323

24-
1. set a real database in phpunit.xml
25-
26-
```xml
27-
28-
<phpunit>
29-
<php>
30-
<!-- DB_CONNECTION can't be %memory% -->
31-
<server name="DB_CONNECTION" value="sqlite"/>
32-
<server name="DB_DATABASE" value="database/database.sqlite"/>
33-
</php>
34-
</phpunit>
35-
```
36-
37-
2. make a product migration
24+
- make a product migration
3825

3926
```php
4027
<?php
@@ -74,7 +61,7 @@ class CreateProductsTable extends Migration
7461

7562
```
7663

77-
3. define product model `App\Models\Product`
64+
- define product model `App\Models\Product`
7865

7966
```php
8067
<?php
@@ -104,7 +91,7 @@ class Product extends Model
10491

10592
```
10693

107-
4. define router in `routes/web.php`
94+
- define router in `routes/web.php`
10895

10996
```php
11097
<?php
@@ -133,7 +120,7 @@ Route::post('/product/{productId}', function ($productId) {
133120

134121
```
135122

136-
5. testing
123+
- testing
137124

138125
```php
139126
<?php
@@ -142,24 +129,23 @@ namespace Tests\Feature;
142129

143130
use App\Models\Product;
144131
use Illuminate\Foundation\Testing\DatabaseMigrations;
132+
use Recca0120\LaravelParallel\Tests\Concerns\WithParallelPhyiscalDatabase;
145133
use Recca0120\LaravelParallel\Tests\ParallelRequest;
146134
use Tests\TestCase;
147135

148136
class RaceConditionTest extends TestCase
149137
{
150138
use DatabaseMigrations;
139+
use WithParallelPhyiscalDatabase;
151140

152141
private $product;
153142
private $quantity = 10;
154143

155-
public function setUp(): void
156-
{
157-
parent::setUp();
158-
$this->product = Product::create(['name' => 'test', 'quantity' => $this->quantity]);
159-
}
160-
161144
public function test_race_condition()
162145
{
146+
$this->useParallelPhyiscalDatabase();
147+
148+
$this->product = Product::create(['name' => 'test', 'quantity' => $this->quantity]);
163149
$request = $this->app->make(ParallelRequest::class);
164150

165151
$promises = collect();
@@ -178,6 +164,10 @@ class RaceConditionTest extends TestCase
178164

179165
public function test_multiple_times_to_test_race_condition()
180166
{
167+
$this->useParallelPhyiscalDatabase();
168+
169+
$this->product = Product::create(['name' => 'test', 'quantity' => $this->quantity]);
170+
181171
$request = $this->app->make(ParallelRequest::class);
182172

183173
$promises = collect($request->times(10)->post('/product/'.$this->product->id));

composer.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"description": "",
44
"keywords": [
55
"laravel",
6-
"testing",
76
"parallel",
87
"parallel request"
98
],

src/ParallelServiceProvider.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Recca0120\LaravelParallel;
44

5+
use Illuminate\Http\Request;
56
use Illuminate\Support\ServiceProvider;
67
use Recca0120\LaravelParallel\Console\ParallelCommand;
78

@@ -19,5 +20,12 @@ public function register()
1920
]);
2021

2122
$this->commands([ParallelCommand::class]);
23+
24+
$this->app->bind(ParallelRequest::class, function () {
25+
/** @var Request $request */
26+
$request = app('request');
27+
28+
return (new ParallelRequest($request))->withServerVariables($request->server->all());
29+
});
2230
}
2331
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
namespace Recca0120\LaravelParallel\Tests\Concerns;
4+
5+
use Illuminate\Contracts\Console\Kernel;
6+
use Illuminate\Foundation\Testing\DatabaseMigrations;
7+
use Illuminate\Foundation\Testing\RefreshDatabase;
8+
use Illuminate\Foundation\Testing\RefreshDatabaseState;
9+
use Illuminate\Foundation\Testing\Traits\CanConfigureMigrationCommands;
10+
use Illuminate\Http\Request;
11+
use Illuminate\Support\Arr;
12+
use Illuminate\Support\Facades\File;
13+
use Illuminate\Support\Str;
14+
use Recca0120\LaravelParallel\Tests\ParallelRequest;
15+
16+
trait WithParallelPhyiscalDatabase
17+
{
18+
use CanConfigureMigrationCommands;
19+
20+
private $parallelDatabaseName = 'laravel-parallel';
21+
22+
public function useParallelPhyiscalDatabase(): void
23+
{
24+
$this->setParallelPhyiscalDatabase();
25+
$this->refreshParallelPhyiscalDatabase();
26+
$this->bindParallelRequest();
27+
}
28+
29+
protected function setParallelPhyiscalDatabase(): void
30+
{
31+
if ($this->usingPhyiscalDatabase()) {
32+
return;
33+
}
34+
35+
$config = collect(Arr::dot(config()->all()))
36+
->filter(function ($value, $key) {
37+
return $value && Str::endsWith($key, 'database.connection');
38+
})
39+
->map(function () {
40+
return $this->parallelDatabaseName;
41+
})
42+
->merge(['database.default' => $this->parallelDatabaseName])
43+
->toArray();
44+
45+
config($config);
46+
47+
File::put(config('database.connections.'.$this->parallelDatabaseName.'.database'), '');
48+
}
49+
50+
protected function refreshParallelPhyiscalDatabase(): void
51+
{
52+
$this->artisan('migrate:fresh', $this->migrateFreshUsing());
53+
54+
$this->app[Kernel::class]->setArtisan(null);
55+
56+
$uses = array_flip(class_uses_recursive(static::class));
57+
foreach ([RefreshDatabase::class, DatabaseMigrations::class] as $class) {
58+
if (array_key_exists($class, $uses)) {
59+
RefreshDatabaseState::$migrated = false;
60+
RefreshDatabaseState::$lazilyRefreshed = false;
61+
62+
return;
63+
}
64+
}
65+
}
66+
67+
/**
68+
* @return void
69+
*/
70+
private function bindParallelRequest(): void
71+
{
72+
$this->app->bind(ParallelRequest::class, function () {
73+
/** @var Request $request */
74+
$request = app('request');
75+
$default = config('database.default');
76+
77+
return (new ParallelRequest($request))->withServerVariables(array_merge($request->server->all(), [
78+
'DB_CONNECTION' => $default,
79+
'DB_DATABASE' => config('database.connections.'.$default.'.database'),
80+
]));
81+
});
82+
}
83+
84+
protected function usingPhyiscalDatabase(): bool
85+
{
86+
$default = config('database.default');
87+
88+
return config("database.connections.$default.database") !== ':memory:';
89+
}
90+
}

0 commit comments

Comments
 (0)