Files
transmit/app/inquery/utils/RoundRobinAssigner.php
T

47 lines
1.5 KiB
PHP
Raw Normal View History

2025-12-15 02:22:19 +00:00
<?php
namespace app\inquery\utils;
use support\Redis;
use support\exception\BusinessException;
class RoundRobinAssigner
{
/**
* Redis key 前缀
* 你可以按业务分组:比如 "fb_inquiry", "website_inquiry" 等
*/
protected const REDIS_KEY_PREFIX = 'inquiry:assign:round_robin:';
/**
* 从一组业务员 ID 中按轮询规则返回“下一个业务员 ID”
*
* @param int[] $userIds 业务员 ID 列表(有顺序)
* @param string $groupKey 分配分组标识(同一个分组共享一个轮询指针)
*
* @return int 下一位业务员 ID
* @throws BusinessException
*/
public static function nextUserId(array $userIds, string $groupKey = 'default'): int
{
// 校验
$userIds = array_values(array_filter(array_map('intval', $userIds), fn($v) => $v > 0));
if (empty($userIds)) {
throw new BusinessException('轮询分配业务员失败:业务员列表不能为空');
}
$count = count($userIds);
// Redis key:同一个 groupKey 共用一条轮询链
$key = self::REDIS_KEY_PREFIX . $groupKey;
// 使用 INCR 做自增计数,天然是原子操作,适合并发环境
// 第一次调用 INCR 返回 1,我们用 (value - 1) 来做索引,从 0 开始
$val = Redis::incr($key); // 如果不存在,Redis 会先置为 0 再加 1
$index = ($val - 1) % $count;
return $userIds[$index];
}
}