/// <summary> /// Take responsibility for a set of new queues that were assigned to me via a new range. /// We first create one pulling agent for every new queue and store them in our internal data structure, then try to initialize the agents. /// ERROR HANDLING: /// The responsibility to handle initialization and shutdown failures is inside the Agents code. /// The manager will call Initialize once and log an error. It will not call initialize again and will assume initialization has succeeded. /// Same applies to shutdown. /// </summary> /// <param name="myQueues"></param> /// <param name="failOnInit"></param> /// <returns></returns> private async Task AddNewQueues(IEnumerable <QueueId> myQueues, bool failOnInit) { // Create agents for queues in range that we don't yet have. // First create them and store in local queuesToAgentsMap. // Only after that Initialize them all. var agents = new List <PersistentStreamPullingAgent>(); foreach (var queueId in myQueues.Where(queueId => !queuesToAgentsMap.ContainsKey(queueId))) { try { var agentId = GrainId.NewSystemTargetGrainIdByTypeCode(Constants.PULLING_AGENT_SYSTEM_TARGET_TYPE_CODE); var agent = new PersistentStreamPullingAgent(agentId, streamProviderName, providerRuntime, queueId, queueGetPeriod, initQueueTimeout); providerRuntime.RegisterSystemTarget(agent); queuesToAgentsMap.Add(queueId, agent); agents.Add(agent); } catch (Exception exc) { logger.Error((int)ErrorCode.PersistentStreamPullingManager_07, String.Format("Exception while creating PersistentStreamPullingAgent."), exc); // What should we do? This error is not recoverable and considered a bug. But we don't want to bring the silo down. // If this is when silo is starting and agent is initializing, fail the silo startup. Otherwise, just swallow to limit impact on other receivers. if (failOnInit) { throw; } } } try { var initTasks = new List <Task>(); foreach (var agent in agents) { // Init the agent only after it was registered locally. var agentGrainRef = PersistentStreamPullingAgentFactory.Cast(agent.AsReference()); // Need to call it as a grain reference. var task = OrleansTaskExtentions.SafeExecute(() => agentGrainRef.Initialize(((IQueueAdapter)queueAdapter).AsImmutable())); task = task.LogException(logger, ErrorCode.PersistentStreamPullingManager_08, String.Format("PersistentStreamPullingAgent {0} failed to Initialize.", agent.QueueId)); initTasks.Add(task); } await Task.WhenAll(initTasks); } catch (Exception) { // Just ignore this exception and proceed as if Initialize has succeeded. // We already logged individual exceptions for individual calls to Initialize. No need to log again. } logger.Info((int)ErrorCode.PersistentStreamPullingManager_09, "Took {0} new queues under my responsibility: {1}", agents.Count, Utils.EnumerableToString(agents, agent => agent.QueueId.ToStringWithHashCode())); }
private async Task RemoveQueues(IEnumerable <QueueId> myQueues) { // Stop the agents that for queues that are not in my range anymore. List <QueueId> queuesToRemove = queuesToAgentsMap.Keys.Where(queueId => !myQueues.Contains(queueId)).ToList(); var agents = new List <PersistentStreamPullingAgent>(queuesToRemove.Count); logger.Info((int)ErrorCode.PersistentStreamPullingManager_10, "Removing {0} agents from my responsibility: {1}", queuesToRemove.Count, Utils.EnumerableToString(queuesToRemove, q => q.ToStringWithHashCode())); var removeTasks = new List <Task>(); foreach (var queueId in queuesToRemove) { PersistentStreamPullingAgent agent; if (!queuesToAgentsMap.TryGetValue(queueId, out agent)) { continue; } agents.Add(agent); queuesToAgentsMap.Remove(queueId); var agentGrainRef = PersistentStreamPullingAgentFactory.Cast(agent.AsReference()); var task = OrleansTaskExtentions.SafeExecute(agentGrainRef.Shutdown); task = task.LogException(logger, ErrorCode.PersistentStreamPullingManager_11, String.Format("PersistentStreamPullingAgent {0} failed to Shutdown.", agent.QueueId)); removeTasks.Add(task); } try { await Task.WhenAll(removeTasks); } catch (Exception) { // Just ignore this exception and proceed as if Initialize has succeeded. // We already logged individual exceptions for individual calls to Shutdown. No need to log again. } foreach (var agent in agents) { try { providerRuntime.UnRegisterSystemTarget(agent); } catch (Exception exc) { logger.Info((int)ErrorCode.PersistentStreamPullingManager_12, "Exception while UnRegisterSystemTarget of PersistentStreamPullingAgent {0}. Ignoring. Exc.Message = {1}.", agent.GrainId, exc.Message); } } }