56 lines
2.9 KiB
PHP
56 lines
2.9 KiB
PHP
|
|
<?php
|
|||
|
|
|
|||
|
|
declare(strict_types=1);
|
|||
|
|
|
|||
|
|
namespace Tests\Concerns;
|
|||
|
|
|
|||
|
|
use Illuminate\Database\Connection;
|
|||
|
|
use Illuminate\Support\Facades\DB;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Share PDO между pgsql и pgsql_admin connections в тестах.
|
|||
|
|
*
|
|||
|
|
* Зачем: middleware UseAdminConnection (alias admin-db) на группе saas-admin
|
|||
|
|
* переключает default-подключение на pgsql_admin (роль crm_admin_user). В тестах
|
|||
|
|
* DatabaseTransactions оборачивает каждый connection в свою транзакцию: данные,
|
|||
|
|
* засеянные через default Tenant::factory() ($pgsql), не видны с pgsql_admin
|
|||
|
|
* connection до commit'а → admin-эндпоинты в тестах видят 0 строк / 404.
|
|||
|
|
* Sharing PDO означает — обе connection используют ту же PDO session → одну
|
|||
|
|
* транзакцию, и засеянные данные видны admin-контроллеру.
|
|||
|
|
*
|
|||
|
|
* На production обе connection реальные separate PDO; pgsql_admin (srv_bypass)
|
|||
|
|
* видит все тенанты по READ COMMITTED. Этот trait — только для test-окружения.
|
|||
|
|
*
|
|||
|
|
* Зеркало [[SharesSupplierPdo]] для pgsql_admin. Применяется глобально к Feature
|
|||
|
|
* suite (см. tests/Pest.php), т.к. admin-db висит на всей группе saas-admin —
|
|||
|
|
* любой admin-тест (текущий и будущий) получает cross-connection visibility без
|
|||
|
|
* per-file opt-in. Для не-admin тестов инертен (pgsql_admin просто не запрашивают).
|
|||
|
|
*/
|
|||
|
|
trait SharesAdminPdo
|
|||
|
|
{
|
|||
|
|
protected function setUpSharesAdminPdo(): void
|
|||
|
|
{
|
|||
|
|
if (! config()->has('database.connections.pgsql_admin')) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$defaultConnection = DB::connection('pgsql');
|
|||
|
|
$adminConnection = DB::connection('pgsql_admin');
|
|||
|
|
$adminConnection->setPdo($defaultConnection->getPdo());
|
|||
|
|
$adminConnection->setReadPdo($defaultConnection->getReadPdo());
|
|||
|
|
|
|||
|
|
// Синхронизируем уровень вложенности транзакции: DatabaseTransactions уже
|
|||
|
|
// открыл транзакцию на pgsql (тот же PDO) к моменту setUp. Без синхронизации
|
|||
|
|
// pgsql_admin считает transactions=0 и при ->transaction() зовёт
|
|||
|
|
// PDO->beginTransaction() на уже активной транзакции → PDOException
|
|||
|
|
// "There is already an active transaction" (например AdminTenantsController::
|
|||
|
|
// updateBalance). С синхронизацией вложенный transaction() делает SAVEPOINT.
|
|||
|
|
$level = $defaultConnection->transactionLevel();
|
|||
|
|
if ($level > 0) {
|
|||
|
|
$prop = new \ReflectionProperty(Connection::class, 'transactions');
|
|||
|
|
$prop->setAccessible(true);
|
|||
|
|
$prop->setValue($adminConnection, $level);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|