165 lines
5.2 KiB
PHP
165 lines
5.2 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
namespace HyperfTest\Cases\Unit\Platform;
|
||
|
|
|
||
|
|
use App\Model\AggregateRefreshQueue;
|
||
|
|
use App\Platform\OrderConsumer;
|
||
|
|
use Carbon\Carbon;
|
||
|
|
use PHPUnit\Framework\TestCase;
|
||
|
|
use ReflectionMethod;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @internal
|
||
|
|
* @coversNothing
|
||
|
|
*/
|
||
|
|
class OrderConsumerEnqueueTest extends TestCase
|
||
|
|
{
|
||
|
|
protected function runInCoroutine(callable $callback): void
|
||
|
|
{
|
||
|
|
if (\Swoole\Coroutine::getCid() > 0) {
|
||
|
|
$callback();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
$exception = null;
|
||
|
|
\Swoole\Coroutine\run(static function () use ($callback, &$exception): void {
|
||
|
|
try {
|
||
|
|
$callback();
|
||
|
|
} catch (\Throwable $e) {
|
||
|
|
$exception = $e;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
if ($exception) {
|
||
|
|
throw $exception;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 调用 protected enqueueAffectedDates 方法
|
||
|
|
*/
|
||
|
|
protected function invokeEnqueue(array $payloads): void
|
||
|
|
{
|
||
|
|
$consumer = new OrderConsumer();
|
||
|
|
$method = new ReflectionMethod($consumer, 'enqueueAffectedDates');
|
||
|
|
$method->setAccessible(true);
|
||
|
|
$method->invoke($consumer, $payloads);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 清理指定日期的队列条目(前置 + 后置双保险)
|
||
|
|
*/
|
||
|
|
protected function cleanupQueue(string $date): void
|
||
|
|
{
|
||
|
|
AggregateRefreshQueue::query()
|
||
|
|
->where('refresh_date', $date)
|
||
|
|
->where('aggregate_view', 'orders_daily_by_created')
|
||
|
|
->delete();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 当日订单不应入队(在自动刷新策略覆盖窗口内)
|
||
|
|
*/
|
||
|
|
public function test_today_payload_does_not_enqueue(): void
|
||
|
|
{
|
||
|
|
$this->runInCoroutine(function (): void {
|
||
|
|
$today = Carbon::now()->toDateString();
|
||
|
|
$payloads = [['created_date' => Carbon::now()->format('Y-m-d H:i:sP')]];
|
||
|
|
|
||
|
|
$this->cleanupQueue($today);
|
||
|
|
try {
|
||
|
|
$this->invokeEnqueue($payloads);
|
||
|
|
|
||
|
|
$row = AggregateRefreshQueue::query()
|
||
|
|
->where('refresh_date', $today)
|
||
|
|
->where('aggregate_view', 'orders_daily_by_created')
|
||
|
|
->first();
|
||
|
|
$this->assertNull($row);
|
||
|
|
} finally {
|
||
|
|
$this->cleanupQueue($today);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 2 天前订单不应入队(仍在自动刷新策略 [now-3d, now-1h] 窗口内)
|
||
|
|
*/
|
||
|
|
public function test_two_days_ago_payload_does_not_enqueue(): void
|
||
|
|
{
|
||
|
|
$this->runInCoroutine(function (): void {
|
||
|
|
$two_days_ago = Carbon::now()->subDays(2)->toDateString();
|
||
|
|
$payloads = [['created_date' => Carbon::now()->subDays(2)->format('Y-m-d H:i:sP')]];
|
||
|
|
|
||
|
|
$this->cleanupQueue($two_days_ago);
|
||
|
|
try {
|
||
|
|
$this->invokeEnqueue($payloads);
|
||
|
|
|
||
|
|
$row = AggregateRefreshQueue::query()
|
||
|
|
->where('refresh_date', $two_days_ago)
|
||
|
|
->where('aggregate_view', 'orders_daily_by_created')
|
||
|
|
->first();
|
||
|
|
$this->assertNull($row);
|
||
|
|
} finally {
|
||
|
|
$this->cleanupQueue($two_days_ago);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 30 天前订单应入队 by_created(自动策略未覆盖,需补刷)
|
||
|
|
*/
|
||
|
|
public function test_old_payload_enqueues_by_created(): void
|
||
|
|
{
|
||
|
|
$this->runInCoroutine(function (): void {
|
||
|
|
$old_date = Carbon::now()->subDays(30)->toDateString();
|
||
|
|
$payloads = [['created_date' => Carbon::now()->subDays(30)->format('Y-m-d H:i:sP')]];
|
||
|
|
|
||
|
|
$this->cleanupQueue($old_date);
|
||
|
|
try {
|
||
|
|
$this->invokeEnqueue($payloads);
|
||
|
|
|
||
|
|
$row = AggregateRefreshQueue::query()
|
||
|
|
->where('refresh_date', $old_date)
|
||
|
|
->where('aggregate_view', 'orders_daily_by_created')
|
||
|
|
->first();
|
||
|
|
$this->assertNotNull($row);
|
||
|
|
$this->assertSame($old_date, $row->refresh_date);
|
||
|
|
$this->assertSame('orders_daily_by_created', $row->aggregate_view);
|
||
|
|
} finally {
|
||
|
|
$this->cleanupQueue($old_date);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 同日期重复入队由复合主键 + insertOrIgnore 防重
|
||
|
|
*/
|
||
|
|
public function test_dedup_via_insert_or_ignore(): void
|
||
|
|
{
|
||
|
|
$this->runInCoroutine(function (): void {
|
||
|
|
$old_date = Carbon::now()->subDays(45)->toDateString();
|
||
|
|
$payloads = [
|
||
|
|
['created_date' => Carbon::now()->subDays(45)->format('Y-m-d H:i:sP')],
|
||
|
|
['created_date' => Carbon::now()->subDays(45)->format('Y-m-d H:i:sP')],
|
||
|
|
];
|
||
|
|
|
||
|
|
$this->cleanupQueue($old_date);
|
||
|
|
try {
|
||
|
|
// 单批次内同日期 → $unique_dates map 去重
|
||
|
|
$this->invokeEnqueue($payloads);
|
||
|
|
// 跨批次同日期 → 复合主键 insertOrIgnore 防重
|
||
|
|
$this->invokeEnqueue($payloads);
|
||
|
|
|
||
|
|
$count = AggregateRefreshQueue::query()
|
||
|
|
->where('refresh_date', $old_date)
|
||
|
|
->where('aggregate_view', 'orders_daily_by_created')
|
||
|
|
->count();
|
||
|
|
$this->assertSame(1, $count);
|
||
|
|
} finally {
|
||
|
|
$this->cleanupQueue($old_date);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|