修复上游业务页面快照完整性 #2

Merged
WuYongJie merged 2 commits from fix/WuYongJie-upstream-snapshot-readiness into main 2026-08-03 18:22:46 +08:00
2 changed files with 46 additions and 0 deletions

View File

@ -176,6 +176,18 @@ class UpstreamQueryCache
return $urgent;
}
// 首份快照和过期快照都标记为 urgent。对于这些请求,必须让
// 等待最久的查询先执行;否则持续出现的新列表查询会凭借下方
// 的类型优先级,长期挤掉同一页面的 summary/options,页面就会
// 一直停在“列表有了,但汇总或筛选项仍 503”的半完成状态。
if ((bool) ($a['urgent'] ?? false)) {
$oldest = ((int) ($a['seen_at'] ?? 0)) <=> ((int) ($b['seen_at'] ?? 0));
if ($oldest !== 0) {
return $oldest;
}
}
$priority = $this->priorityFor((string) $b['scope']) <=> $this->priorityFor((string) $a['scope']);
if ($priority !== 0) {

View File

@ -162,4 +162,38 @@ class JianSunQueryCacheTest extends TestCase
$this->assertSame(0, $calls);
}
}
public function test_oldest_urgent_snapshot_is_not_starved_by_newer_list_queries(): void
{
config()->set('upstreams.snapshots.allow_inline_refresh', false);
$cache = app(JianSunQueryCache::class);
$this->registerColdQuery($cache, 'goods.options');
$registry = Cache::get('jiansun:snapshots:active:v2');
$oldestKey = array_key_first($registry);
$registry[$oldestKey]['seen_at'] = time() - 30;
Cache::forever('jiansun:snapshots:active:v2', $registry);
$this->registerColdQuery($cache, 'invoice-deductions.list');
$this->registerColdQuery($cache, 'invoice-deductions.summary');
$entries = $cache->activeEntries(2);
$this->assertSame('goods.options', $entries[0]['scope']);
$this->assertContains(
$entries[1]['scope'],
['invoice-deductions.list', 'invoice-deductions.summary']
);
}
private function registerColdQuery(JianSunQueryCache $cache, string $scope): void
{
try {
$cache->remember($scope, [], fn (): array => []);
$this->fail('关闭页面内刷新时,冷查询应登记后返回暂不可用。');
} catch (ServiceUnavailableHttpException) {
$this->assertTrue(true);
}
}
}