CaiWuXiTong/app/Console/Commands/UpstreamRefreshAllSnapshots.php

95 lines
3.2 KiB
PHP

<?php
namespace App\Console\Commands;
use Illuminate\Cache\CacheManager;
use Illuminate\Contracts\Cache\Repository;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\EcommerceFinance\Services\UpstreamSnapshotRefresherRegistry;
use Throwable;
class UpstreamRefreshAllSnapshots extends Command
{
protected $signature = 'upstream:snapshots:refresh-all
{--limit= : 每个来源本轮最多刷新的活跃查询数}';
protected $description = '使用共享锁刷新所有已经登记刷新器的上游活跃查询';
public function handle(
UpstreamSnapshotRefresherRegistry $refreshers,
CacheManager $cacheManager,
): int {
// 每分钟运行的后台刷新周期只会在目录超过 24 小时时真正读取一次元数据。
// 失败不阻断已有业务快照刷新,原有数据字典也会被保留。
$this->call('upstream:schema:sync', ['--due' => true]);
$storeName = (string) config('upstreams.snapshots.cache_store', 'upstream_shared');
$cache = $cacheManager->store($storeName);
$failed = false;
foreach ($refreshers->sources() as $source) {
$lock = $cache->lock('refresh-cycle:' . $source, 180);
if (! $lock->get()) {
continue;
}
try {
$arguments = ['source' => $source];
if ($this->option('limit') !== null) {
$arguments['--limit'] = (int) $this->option('limit');
}
if ($this->call('upstream:snapshots:refresh', $arguments) !== self::SUCCESS) {
$failed = true;
}
} catch (Throwable $exception) {
$failed = true;
Log::error('上游共享快照刷新周期失败,已继续处理其他来源。', [
'source' => $source,
'exception' => $exception::class,
]);
} finally {
$lock->release();
}
}
$this->pruneExpiredSharedEntries($cache, $storeName);
return $failed ? self::FAILURE : self::SUCCESS;
}
private function pruneExpiredSharedEntries(Repository $cache, string $storeName): void
{
$window = now()->format('YmdH');
if (! $cache->add('prune-window:' . $window, true, 7200)) {
return;
}
$store = (array) config('cache.stores.' . $storeName, []);
if (($store['driver'] ?? null) !== 'database') {
return;
}
try {
$connection = DB::connection($store['connection'] ?? null);
$expiration = time();
$connection->table((string) ($store['table'] ?? 'upstream_query_cache'))
->where('expiration', '<=', $expiration)
->delete();
$connection->table((string) ($store['lock_table'] ?? 'upstream_query_locks'))
->where('expiration', '<=', $expiration)
->delete();
} catch (Throwable $exception) {
Log::warning('清理过期上游共享快照失败。', [
'exception' => $exception::class,
]);
}
}
}