/// <summary> /// 获取一个可以工作的机器人 /// </summary> /// <param name="clientKey">客户的唯一标识</param> /// <param name="type">申请机器人的类型</param> /// <returns>一台可工作的机器人</returns> public IRobot ApplyOneAvailableRobot(RobotType type, string clientKey = null) { IRobot robot = null; if (String.IsNullOrEmpty(clientKey)) { throw new ArgumentException("Client Key 不能为空"); } // 1. 如果之前有注册机器人,则继续使用 if (_roster.ContainsKey(clientKey)) { string apiKey = _roster[clientKey]; RobotStruct robotStruct = _robots[apiKey]; if (robotStruct.RobotType != type) { throw new UnmatchedTypeException(robotStruct.RobotType, "已经注册了不同类型的机器人"); } robot = robotStruct.Robot; return(robot); } // 2. 如果是共享类型的机器人,则搜索 if (RobotType.Public == type) { foreach (string apiKey in _robots.Keys) { RobotStruct robotStruct = _robots[apiKey]; if (RobotType.Public == robotStruct.RobotType && robotStruct.CanRegister()) { if (robotStruct.Register(clientKey)) { robot = robotStruct.Robot; return(robot); } } } } // 3. 找不到合适的机器人,则创建新的机器人,并加入池中 robot = CreateRobot(clientKey, type); return(robot); }
/// <summary> /// 创建机器人实例 /// </summary> private IRobot CreateRobot(string clientKey, RobotType type) { IRobot registeredRobot = null; // 加锁,主要防止同时并发创建机器人实例对象 lock (this) { if (_robots.Count >= _maxRobot) { throw new MaxRobotException(_maxRobot); } int newRobotCount = 0; if (RobotType.Private == type) { newRobotCount = 1; } else if (RobotType.Public == type) { newRobotCount = _newRobot; if (_robots.Count + _newRobot >= _maxRobot) { newRobotCount = _maxRobot - _robots.Count; } } // 创建机器人 int maxClientPerRobot = _maxClientPerRobot; if (RobotType.Private == type) { maxClientPerRobot = 1; } foreach (string key in APIKeys) { if (newRobotCount <= 0) { break; } if (!_robots.ContainsKey(key)) { newRobotCount--; IRobot robot = new Robot(APIBaseURL, key); RobotStruct robotStruct = new RobotStruct(robot, type, maxClientPerRobot); if (null == registeredRobot) { robotStruct.Register(clientKey); registeredRobot = robotStruct.Robot; _roster.Add(clientKey, key); } _robots.Add(key, robotStruct); } } } return(registeredRobot); }