130 lines
4.8 KiB
PHP
130 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\SystemSettings;
|
|
|
|
use App\Models\Auth\Permission;
|
|
use Illuminate\Cache\CacheManager;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Modules\EcommerceFinance\Services\UpstreamQueryCache;
|
|
use Modules\EcommerceFinance\Services\UpstreamSourceRegistry;
|
|
use Tests\TestCase;
|
|
|
|
class UpstreamSharedDatabaseCacheTest extends TestCase
|
|
{
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
config()->set('upstreams.stored_configuration.enabled', false);
|
|
config()->set('upstreams.local_configuration.enabled', true);
|
|
config()->set('upstreams.snapshots.cache_store', 'upstream_shared');
|
|
config()->set('upstreams.runtime.max_concurrency', 4);
|
|
config()->set('upstreams.runtime.slot_wait_ms', 0);
|
|
config()->set('upstreams.sources.shared_source', [
|
|
'label' => '共享来源',
|
|
'config' => 'test_shared_source',
|
|
]);
|
|
config()->set('test_shared_source', [
|
|
'enabled' => true,
|
|
'allowed_scopes' => ['orders.*'],
|
|
'connection' => [
|
|
'connect_timeout' => 1,
|
|
'query_timeout' => 1,
|
|
],
|
|
'snapshots' => [
|
|
'ttl_seconds' => 60,
|
|
'summary_ttl_seconds' => 60,
|
|
'options_ttl_seconds' => 3600,
|
|
'stale_ttl_seconds' => 3600,
|
|
'active_ttl_seconds' => 3600,
|
|
'registry_limit' => 50,
|
|
'refresh_limit' => 2,
|
|
'miss_budget_per_window' => 6,
|
|
'budget_window_seconds' => 60,
|
|
'lock_seconds' => 15,
|
|
'lock_wait_seconds' => 1,
|
|
'max_concurrency' => 2,
|
|
'slot_wait_ms' => 0,
|
|
'failure_cooldown_seconds' => 60,
|
|
'query_failure_cooldown_seconds' => 60,
|
|
'slow_query_ms' => 5000,
|
|
'slow_query_cooldown_seconds' => 60,
|
|
'refresh_time_budget_seconds' => 10,
|
|
'refresh_pause_ms' => 0,
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function test_two_runtime_instances_share_one_database_snapshot_without_copying_source_tables(): void
|
|
{
|
|
$sources = app(UpstreamSourceRegistry::class);
|
|
$cacheManager = app(CacheManager::class);
|
|
$firstRuntime = new UpstreamQueryCache($sources, 'shared_source', $cacheManager);
|
|
$secondRuntime = new UpstreamQueryCache($sources, 'shared_source', $cacheManager);
|
|
$calls = 0;
|
|
|
|
$first = $firstRuntime->remember('orders.list', ['month' => '2026-07'], function () use (&$calls): array {
|
|
$calls++;
|
|
|
|
return ['rows' => [['id' => 1]], 'total' => 1];
|
|
});
|
|
$second = $secondRuntime->remember('orders.list', ['month' => '2026-07'], function () use (&$calls): array {
|
|
$calls++;
|
|
|
|
return ['rows' => [['id' => 999]], 'total' => 999];
|
|
});
|
|
|
|
$this->assertSame($first, $second);
|
|
$this->assertSame(1, $calls);
|
|
$this->assertGreaterThan(0, DB::table('upstream_query_cache')->count());
|
|
$this->assertTrue(Schema::hasTable('upstream_query_cache'));
|
|
$this->assertTrue(Schema::hasTable('upstream_query_locks'));
|
|
$this->assertFalse(Schema::hasTable('orders'));
|
|
}
|
|
|
|
public function test_refresh_all_safely_skips_a_registered_but_disabled_source(): void
|
|
{
|
|
config()->set('jiansun.enabled', false);
|
|
|
|
$this->artisan('upstream:snapshots:refresh-all')
|
|
->expectsOutputToContain('同步未启用,本轮跳过')
|
|
->assertExitCode(0);
|
|
}
|
|
|
|
public function test_permission_change_creates_a_separate_snapshot_scope(): void
|
|
{
|
|
$user = user_model_class()::firstOrFail();
|
|
$user->companies()->firstOrFail()->makeCurrent();
|
|
$this->actingAs($user);
|
|
$sources = app(UpstreamSourceRegistry::class);
|
|
$cacheManager = app(CacheManager::class);
|
|
$calls = 0;
|
|
|
|
$before = (new UpstreamQueryCache($sources, 'shared_source', $cacheManager))
|
|
->remember('orders.list', [], function () use (&$calls): array {
|
|
$calls++;
|
|
|
|
return ['permission_version' => 1];
|
|
});
|
|
|
|
$permission = Permission::query()->create([
|
|
'name' => 'read-shared-snapshot-test',
|
|
'display_name' => 'Read Shared Snapshot Test',
|
|
'description' => '测试共享快照权限隔离',
|
|
]);
|
|
$user->attachPermission($permission);
|
|
|
|
$after = (new UpstreamQueryCache($sources, 'shared_source', $cacheManager))
|
|
->remember('orders.list', [], function () use (&$calls): array {
|
|
$calls++;
|
|
|
|
return ['permission_version' => 2];
|
|
});
|
|
|
|
$this->assertSame(1, $before['permission_version']);
|
|
$this->assertSame(2, $after['permission_version']);
|
|
$this->assertSame(2, $calls);
|
|
}
|
|
}
|