Files
portal/app/tests/Concerns/SharesAdminPdo.php
T
Дмитрий b38fe0c875 feat(админка): admin-db middleware в группе saas-admin + SharesAdminPdo для тестов
bootstrap: alias admin-db=UseAdminConnection; web.php: группа saas-admin теперь
['saas-admin','admin-db'] (swap default→pgsql_admin после гейта). Тест: admin-db
в пайплайне /api/admin/tenants, saas-admin не потерян.

SharesAdminPdo (зеркало SharesSupplierPdo) применён глобально к Feature suite
(Pest.php): admin-db висит на всей группе → admin-эндпоинты в тестах читают
через pgsql_admin (separate PDO) и не видели бы засеянные в транзакции данные;
sharing PDO даёт cross-connection visibility. baseline: +trait.unused
(Pest применяет трейт в рантайме, phpstan не видит uses() из Pest.php).
261 supplier+admin тестов зелёные.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 06:54:23 +03:00

56 lines
2.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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);
}
}
}