v0.1.0 核心功能: - 更新源管理 (SourceManager, SourceModel, SourceType) - 插件/主题更新器 (PluginUpdater, ThemeUpdater) - 缓存系统 (CacheManager, HealthChecker, FallbackStrategy) - 安全模块 (Validator, Encryption) - 管理界面 (AdminPage, templates, CSS, JS) - 预设源支持 (ArkPress, AspireCloud) v0.2.0 新增功能: - 性能优化 (ParallelRequestManager, RequestDeduplicator) - 条件请求 (ConditionalRequest - ETag/Last-Modified) - 后台更新 (BackgroundUpdater - WP-Cron) - Git 平台支持 (GitHub, GitLab, Gitee handlers) - WP-CLI 命令 (wp bridge source/check/cache/diagnose/config) 安全修复: - SQL 注入防护 ($wpdb->prepare) - GET 参数清理 (sanitize_text_field) - auth_token 加密存储 (AES-256-CBC) - 缓存键哈希 (md5 + site_url) - 卸载清理 (uninstall.php) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
118 lines
2.7 KiB
PHP
118 lines
2.7 KiB
PHP
<?php
|
|
/**
|
|
* 请求去重器
|
|
*
|
|
* @package WPBridge
|
|
*/
|
|
|
|
namespace WPBridge\Performance;
|
|
|
|
use WPBridge\Core\Logger;
|
|
|
|
// 防止直接访问
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* 请求去重器类
|
|
* 防止短时间内重复请求同一源
|
|
*/
|
|
class RequestDeduplicator {
|
|
|
|
/**
|
|
* 合并窗口时间(秒)
|
|
*
|
|
* @var int
|
|
*/
|
|
const MERGE_WINDOW = 5;
|
|
|
|
/**
|
|
* 锁前缀
|
|
*
|
|
* @var string
|
|
*/
|
|
const LOCK_PREFIX = 'wpbridge_lock_';
|
|
|
|
/**
|
|
* 尝试获取锁
|
|
*
|
|
* @param string $source_id 源 ID
|
|
* @return bool 是否成功获取锁
|
|
*/
|
|
public function acquire_lock( string $source_id ): bool {
|
|
$lock_key = self::LOCK_PREFIX . $source_id;
|
|
|
|
// 检查是否已有锁
|
|
if ( get_transient( $lock_key ) ) {
|
|
Logger::debug( '请求被去重', [ 'source' => $source_id ] );
|
|
return false;
|
|
}
|
|
|
|
// 设置锁
|
|
set_transient( $lock_key, time(), self::MERGE_WINDOW );
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 释放锁
|
|
*
|
|
* @param string $source_id 源 ID
|
|
*/
|
|
public function release_lock( string $source_id ): void {
|
|
delete_transient( self::LOCK_PREFIX . $source_id );
|
|
}
|
|
|
|
/**
|
|
* 检查是否有锁
|
|
*
|
|
* @param string $source_id 源 ID
|
|
* @return bool
|
|
*/
|
|
public function has_lock( string $source_id ): bool {
|
|
return (bool) get_transient( self::LOCK_PREFIX . $source_id );
|
|
}
|
|
|
|
/**
|
|
* 等待锁释放并获取结果
|
|
*
|
|
* @param string $source_id 源 ID
|
|
* @param callable $callback 获取结果的回调
|
|
* @param int $max_wait 最大等待时间(秒)
|
|
* @return mixed
|
|
*/
|
|
public function wait_and_get( string $source_id, callable $callback, int $max_wait = 10 ) {
|
|
$start = time();
|
|
|
|
while ( $this->has_lock( $source_id ) ) {
|
|
if ( ( time() - $start ) >= $max_wait ) {
|
|
Logger::warning( '等待锁超时', [ 'source' => $source_id ] );
|
|
break;
|
|
}
|
|
usleep( 100000 ); // 100ms
|
|
}
|
|
|
|
return $callback();
|
|
}
|
|
|
|
/**
|
|
* 带锁执行操作
|
|
*
|
|
* @param string $source_id 源 ID
|
|
* @param callable $callback 操作回调
|
|
* @return mixed
|
|
*/
|
|
public function execute_with_lock( string $source_id, callable $callback ) {
|
|
if ( ! $this->acquire_lock( $source_id ) ) {
|
|
// 已有请求在进行中,等待结果
|
|
return $this->wait_and_get( $source_id, $callback );
|
|
}
|
|
|
|
try {
|
|
$result = $callback();
|
|
return $result;
|
|
} finally {
|
|
$this->release_lock( $source_id );
|
|
}
|
|
}
|
|
}
|