public void CompleteChore() { IsComplete = true; _logger.Log($"Completed { ChoreName }"); _messageCenter.SendMessage(Owner, $"The chore { ChoreName } is complete."); }
public void AnalyzeWorkload(DateTime now, IMessageCenter messageCenter, MessageFactory messageFactory, SiloMessagingOptions options) { var slowRunningRequestDuration = options.RequestProcessingWarningTime; var longQueueTimeDuration = options.RequestQueueDelayWarningTime; List <string> diagnostics = null; lock (this) { if (State != ActivationState.Valid) { return; } if (this.Blocking is object) { var message = this.Blocking; var timeSinceQueued = now - message.QueuedTime; var executionTime = now - currentRequestStartTime; if (executionTime >= slowRunningRequestDuration) { GetStatusList(ref diagnostics); if (timeSinceQueued.HasValue) { diagnostics.Add($"Message {message} was enqueued {timeSinceQueued} ago and has now been executing for {executionTime}."); } else { diagnostics.Add($"Message {message} has been executing for {executionTime}."); } var response = messageFactory.CreateDiagnosticResponseMessage(message, isExecuting: true, isWaiting: false, diagnostics); messageCenter.SendMessage(response); } } foreach (var running in RunningRequests) { var message = running.Key; var startTime = running.Value; if (ReferenceEquals(message, this.Blocking)) { continue; } // Check how long they've been executing. var executionTime = now - startTime; if (executionTime >= slowRunningRequestDuration) { // Interleaving message X has been executing for a long time GetStatusList(ref diagnostics); var messageDiagnostics = new List <string>(diagnostics) { $"Interleaving message {message} has been executing for {executionTime}." }; var response = messageFactory.CreateDiagnosticResponseMessage(message, isExecuting: true, isWaiting: false, messageDiagnostics); messageCenter.SendMessage(response); } } if (waiting is object) { var queueLength = 1; foreach (var message in waiting) { var waitTime = now - message.QueuedTime; if (waitTime >= longQueueTimeDuration) { // Message X has been enqueued on the target grain for Y and is currently position QueueLength in queue for processing. GetStatusList(ref diagnostics); var messageDiagnostics = new List <string>(diagnostics) { $"Message {message} has been enqueued on the target grain for {waitTime} and is currently position {queueLength} in queue for processing." }; var response = messageFactory.CreateDiagnosticResponseMessage(message, isExecuting: false, isWaiting: true, messageDiagnostics); messageCenter.SendMessage(response); } queueLength++; } } } void GetStatusList(ref List <string> diagnostics) { if (diagnostics is object) { return; } diagnostics = new List <string> { this.ToDetailedString(), $"TaskScheduler status: {this.WorkItemGroup.DumpStatus()}" }; } }
private void ReceiveMessage(Message msg) { MessagingProcessingStatisticsGroup.OnImaMessageReceived(msg); ISchedulingContext context; // Find the activation it targets; first check for a system activation, then an app activation if (msg.TargetGrain.IsSystemTarget) { SystemTarget target = directory.FindSystemTarget(msg.TargetActivation); if (target == null) { MessagingStatisticsGroup.OnRejectedMessage(msg); Message response = this.messageFactory.CreateRejectionResponse(msg, Message.RejectionTypes.Unrecoverable, String.Format("SystemTarget {0} not active on this silo. Msg={1}", msg.TargetGrain, msg)); messageCenter.SendMessage(response); Log.Warn(ErrorCode.MessagingMessageFromUnknownActivation, "Received a message {0} for an unknown SystemTarget: {1}", msg, msg.TargetAddress); return; } context = target.SchedulingContext; switch (msg.Direction) { case Message.Directions.Request: MessagingProcessingStatisticsGroup.OnImaMessageEnqueued(context); scheduler.QueueWorkItem(new RequestWorkItem(target, msg), context); break; case Message.Directions.Response: MessagingProcessingStatisticsGroup.OnImaMessageEnqueued(context); scheduler.QueueWorkItem(new ResponseWorkItem(target, msg), context); break; default: Log.Error(ErrorCode.Runtime_Error_100097, "Invalid message: " + msg); break; } } else { // Run this code on the target activation's context, if it already exists ActivationData targetActivation = directory.FindTarget(msg.TargetActivation); if (targetActivation != null) { lock (targetActivation) { var target = targetActivation; // to avoid a warning about nulling targetActivation under a lock on it if (target.State == ActivationState.Valid) { var overloadException = target.CheckOverloaded(Log); if (overloadException != null) { // Send rejection as soon as we can, to avoid creating additional work for runtime dispatcher.RejectMessage(msg, Message.RejectionTypes.Overloaded, overloadException, "Target activation is overloaded " + target); return; } // Run ReceiveMessage in context of target activation context = new SchedulingContext(target); } else { // Can't use this activation - will queue for another activation target = null; context = null; } EnqueueReceiveMessage(msg, target, context); } } else { // No usable target activation currently, so run ReceiveMessage in system context EnqueueReceiveMessage(msg, null, null); } } }