wpmind/includes/Routing/IntelligentRouter.php
LinuxJoy 0ab7d3582d refactor: 清理兼容层 + Provider 懒加载 + 路由策略可插拔
- 删除 10 个兼容层文件 (~55KB),调用方直接引用模块类
- cost-control 模块改为不可禁用,ModuleLoader 强制启用
- ProviderRegistrar 改用字符串 FQCN,添加 wpmind_provider_map filter
- IntelligentRouter 添加 wpmind_register_routing_strategies action
- routing.php 添加 class_exists() 守卫处理 analytics 模块禁用
- AjaxController analytics 端点添加 class_exists() 守卫
- 更新集成测试移除已删除文件引用

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-07 20:19:35 +08:00

363 lines
10 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Intelligent Router - 智能路由器
*
* 基于策略的 Provider 路由选择
*
* @package WPMind
* @since 1.9.0
*/
declare(strict_types=1);
namespace WPMind\Routing;
use WPMind\Routing\Strategies\AvailabilityStrategy;
use WPMind\Routing\Strategies\CompositeStrategy;
use WPMind\Routing\Strategies\CostStrategy;
use WPMind\Routing\Strategies\LatencyStrategy;
use WPMind\Routing\Strategies\LoadBalancedStrategy;
class IntelligentRouter
{
private static ?IntelligentRouter $instance = null;
/** @var array<string, RoutingStrategyInterface> 已注册的策略 */
private array $strategies = [];
/** @var string 当前激活的策略名称 */
private string $activeStrategy = 'balanced';
/** @var array Provider 配置 */
private array $providers = [];
/**
* 获取单例实例
*/
public static function instance(): IntelligentRouter
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct()
{
$this->register_default_strategies();
$this->load_providers();
$this->load_settings();
}
/**
* 注册默认策略
*/
private function register_default_strategies(): void
{
// 复合策略(推荐)
$this->register_strategy(CompositeStrategy::create_balanced()); // 平衡策略
$this->register_strategy(CompositeStrategy::create_performance()); // 性能优先
$this->register_strategy(CompositeStrategy::create_economic()); // 经济策略
// 基础策略
$this->register_strategy(new LoadBalancedStrategy()); // 负载均衡
/**
* 允许第三方注册自定义路由策略
*
* @since 3.7.0
* @param IntelligentRouter $router 路由器实例
*/
do_action('wpmind_register_routing_strategies', $this);
}
/**
* 加载 Provider 配置
*/
private function load_providers(): void
{
if (function_exists('WPMind\\wpmind')) {
$endpoints = \WPMind\wpmind()->get_custom_endpoints();
foreach ($endpoints as $id => $config) {
if (!empty($config['enabled']) && !empty($config['api_key'])) {
$this->providers[$id] = $config;
}
}
}
}
/**
* 加载路由设置
*/
private function load_settings(): void
{
$settings = get_option('wpmind_routing_settings', array());
$strategy = $settings['strategy'] ?? 'balanced';
// 验证策略是否存在,否则回退到默认
if ( ! isset( $this->strategies[ $strategy ] ) ) {
$strategy = 'balanced';
// 自动修复无效配置
if ( isset( $settings['strategy'] ) ) {
$settings['strategy'] = 'balanced';
update_option('wpmind_routing_settings', $settings);
}
}
$this->activeStrategy = $strategy;
}
/**
* 注册路由策略
*
* @param RoutingStrategyInterface $strategy 策略实例
*/
public function register_strategy(RoutingStrategyInterface $strategy): void
{
$this->strategies[$strategy->get_name()] = $strategy;
}
/**
* 获取所有已注册的策略
*
* @return array<string, array{name: string, display_name: string, description: string}>
*/
public function get_available_strategies(): array
{
$result = [];
foreach ($this->strategies as $name => $strategy) {
$result[$name] = [
'name' => $strategy->get_name(),
'display_name' => $strategy->get_display_name(),
'description' => $strategy->get_description(),
];
}
return $result;
}
/**
* 设置当前策略
*
* @param string $strategyName 策略名称
* @return bool 是否设置成功
*/
public function set_strategy(string $strategyName): bool
{
if (!isset($this->strategies[$strategyName])) {
return false;
}
$this->activeStrategy = $strategyName;
// 保存设置
$settings = get_option('wpmind_routing_settings', []);
$settings['strategy'] = $strategyName;
update_option('wpmind_routing_settings', $settings);
return true;
}
/**
* 获取当前策略名称
*/
public function get_current_strategy(): string
{
return $this->activeStrategy;
}
/**
* 获取当前策略实例
*/
public function get_strategy(?string $name = null): ?RoutingStrategyInterface
{
$name = $name ?? $this->activeStrategy;
// 如果请求的策略不存在,尝试回退到 'balanced'
if ( ! isset( $this->strategies[ $name ] ) && $name !== 'balanced' ) {
// 如果 balanced 也不存在,返回第一个可用策略
if ( isset( $this->strategies['balanced'] ) ) {
$name = 'balanced';
} else {
$name = array_key_first( $this->strategies );
}
}
return $this->strategies[ $name ] ?? null;
}
/**
* 路由请求到最佳 Provider
*
* @param RoutingContext|null $context 路由上下文
* @return string|null 选中的 Provider ID
*/
public function route(?RoutingContext $context = null): ?string
{
$context = $context ?? RoutingContext::create();
$strategy = $this->get_strategy();
if ($strategy === null) {
// 无策略时,返回第一个可用的 Provider
return array_key_first($this->providers);
}
// 如果有首选 Provider 且可用,优先使用
$preferred = $context->get_preferred_provider();
if ($preferred !== null && isset($this->providers[$preferred])) {
if (!$context->is_excluded($preferred)) {
return $preferred;
}
}
return $strategy->select_provider($context, $this->providers);
}
/**
* 获取故障转移链
*
* 返回按策略排序的 Provider 列表
*
* @param RoutingContext|null $context 路由上下文
* @return array<string> Provider ID 列表
*/
public function get_failover_chain(?RoutingContext $context = null): array
{
$context = $context ?? RoutingContext::create();
$strategy = $this->get_strategy();
if ($strategy === null) {
return array_keys($this->providers);
}
$ranked = $strategy->rank_providers($context, $this->providers);
// 如果有首选 Provider放在最前面
$preferred = $context->get_preferred_provider();
if ($preferred !== null && in_array($preferred, $ranked, true)) {
$ranked = array_values(array_diff($ranked, [$preferred]));
array_unshift($ranked, $preferred);
}
return $ranked;
}
/**
* 获取所有 Provider 的路由得分
*
* @param RoutingContext|null $context 路由上下文
* @return array<string, array{score: float, rank: int}>
*/
public function get_provider_scores(?RoutingContext $context = null): array
{
$context = $context ?? RoutingContext::create();
$strategy = $this->get_strategy();
if ($strategy === null) {
return [];
}
$scores = [];
foreach ($this->providers as $providerId => $config) {
$scores[$providerId] = [
'score' => $strategy->calculate_score($providerId, $context),
'name' => $config['display_name'] ?? $providerId,
];
}
// 按得分排序并添加排名
uasort($scores, fn($a, $b) => $b['score'] <=> $a['score']);
$rank = 1;
foreach ($scores as $providerId => &$data) {
$data['rank'] = $rank++;
}
return $scores;
}
/**
* 获取路由状态摘要
*
* @return array 状态信息
*/
public function get_status_summary(): array
{
$context = RoutingContext::create();
$strategy = $this->get_strategy();
return [
'active_strategy' => [
'name' => $this->activeStrategy,
'display_name' => $strategy?->get_display_name() ?? '未知',
'description' => $strategy?->get_description() ?? '',
],
'available_strategies' => $this->get_available_strategies(),
'provider_count' => count($this->providers),
'provider_scores' => $this->get_provider_scores($context),
'recommended' => $this->route($context),
'failover_chain' => $this->get_failover_chain($context),
];
}
/**
* 刷新路由器状态
*/
public function refresh(): void
{
self::$instance = null;
self::instance();
}
/**
* 获取手动设置的 Provider 优先级
*
* @return array<string> Provider ID 列表,按优先级排序
*/
public function get_manual_priority(): array
{
$settings = get_option('wpmind_routing_settings', []);
return $settings['provider_priority'] ?? [];
}
/**
* 设置手动 Provider 优先级
*
* @param array<string> $priority Provider ID 列表,按优先级排序
* @return bool 是否设置成功
*/
public function set_manual_priority(array $priority): bool
{
// 验证所有 Provider ID 都有效
$valid_providers = array_keys($this->providers);
$priority = array_filter($priority, fn($id) => in_array($id, $valid_providers, true));
$settings = get_option('wpmind_routing_settings', []);
$settings['provider_priority'] = array_values($priority);
return update_option('wpmind_routing_settings', $settings);
}
/**
* 清除手动优先级设置
*
* @return bool 是否清除成功
*/
public function clear_manual_priority(): bool
{
$settings = get_option('wpmind_routing_settings', []);
unset($settings['provider_priority']);
return update_option('wpmind_routing_settings', $settings);
}
/**
* 检查是否启用了手动优先级
*
* @return bool
*/
public function has_manual_priority(): bool
{
$priority = $this->get_manual_priority();
return !empty($priority);
}
}