/// <summary> /// This is the one where all the magic starts. Main() so to speak. I will load the settings, connect to tfs and apply the aggregation rules. /// </summary> public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType, object notificationEventArgs, out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties) { var result = new ProcessingResult(); try { //Check if we have a workitem changed event before proceeding if (notificationType == NotificationType.Notification && notificationEventArgs is WorkItemChangedEvent) { var context = new RequestContextWrapper(requestContext); var notification = new NotificationWrapper(notificationType, notificationEventArgs as WorkItemChangedEvent); result = eventProcessor.ProcessEvent(context, notification); } } catch (Exception e) { string message = String.Format("Exception encountered processing notification: {0} \nStack Trace:{1}", e.Message, e.StackTrace); if (e.InnerException != null) { message += String.Format("\n Inner Exception: {0} \nStack Trace:{1}", e.InnerException.Message, e.InnerException.StackTrace); } MiscHelpers.LogMessage(message, true); } statusCode = result.StatusCode; statusMessage = result.StatusMessage; properties = result.ExceptionProperties; return(result.NotificationStatus); }
/// <summary> /// This is the one where all the magic starts. Main() so to speak. I will load the settings, connect to TFS and apply the aggregation rules. /// </summary> public EventNotificationStatus ProcessEvent( IVssRequestContext requestContext, NotificationType notificationType, object notificationEventArgs, out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties) { var logger = new ServerEventLogger(GetDefaultLoggingLevel()); var context = new RequestContextWrapper(requestContext, notificationType, notificationEventArgs); var runtime = RuntimeContext.GetContext( GetServerSettingsFullPath, context, logger, (runtimeContext) => new WorkItemRepository(runtimeContext), (runtimeContext) => new ScriptLibrary(runtimeContext)); if (runtime.HasErrors) { statusCode = 99; statusMessage = string.Join(". ", runtime.Errors); properties = null; return(EventNotificationStatus.ActionPermitted); } var result = new ProcessingResult(); try { // Check if we have a workitem changed event before proceeding if (notificationType == NotificationType.Notification && notificationEventArgs is WorkItemChangedEvent) { using (EventProcessor eventProcessor = new EventProcessor(runtime)) { logger.StartingProcessing(context, context.Notification); result = eventProcessor.ProcessEvent(context, context.Notification); logger.ProcessingCompleted(result); } } } catch (Exception e) { logger.ProcessEventException(e); // notify failure result.StatusCode = -1; result.StatusMessage = "Unexpected error: " + e.Message; result.NotificationStatus = EventNotificationStatus.ActionPermitted; } statusCode = result.StatusCode; statusMessage = result.StatusMessage; properties = result.ExceptionProperties; return(result.NotificationStatus); }
// Locking: // Only 1 channelBinder operation call should be active at any given time. All future calls // will wait on the inputQueue. The semaphore is always released right before the Dispatch on the inputQueue. // This protects a new call racing with an existing operation that is just about to fully complete. public async Task <TryAsyncResult <RequestContext> > TryReceiveAsync(CancellationToken token) { if (Interlocked.CompareExchange(ref pendingOperationSemaphore, 1, 0) == 0) { ActionItem.Schedule(tryReceive, this); } var result = await inputQueue.TryDequeueAsync(token); bool success = result.Success; RequestContextWrapper wrapper = result.Result; if (success && wrapper != null) { return(TryAsyncResult.FromResult(wrapper.RequestContext)); } return(TryAsyncResult <RequestContext> .FailedResult); }