95 lines
3.2 KiB
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,
|
|
]);
|
|
}
|
|
}
|
|
}
|