private bool Integrate() { bool ran = false; while (integrationQueue.IsBlocked) { Thread.Sleep(200); } IntegrationRequest ir = integrationQueue.GetNextRequest(project); if (ir != null && IsRunning) { IDisposable queueLock; if (!integrationQueue.TryLock(out queueLock)) { return(false); } using (queueLock) { // Check to see if this integration request should proceed - Extension point IntegrationStartedEventArgs.EventResult eventResult = FireIntegrationStarted(ir); switch (eventResult) { case IntegrationStartedEventArgs.EventResult.Continue: Log.Info(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Project: '{0}' is first in queue: '{1}' and shall start integration.", project.Name, project.QueueName)); IntegrationStatus status = IntegrationStatus.Unknown; IIntegrationResult result = new IntegrationResult(); ran = true; try { ir.PublishOnSourceControlException = (AmountOfSourceControlExceptions == project.MaxSourceControlRetries) || (project.SourceControlErrorHandling == ThoughtWorks.CruiseControl.Core.Sourcecontrol.Common.SourceControlErrorHandlingPolicy.ReportEveryFailure); result = project.Integrate(ir); if (result != null) { status = result.Status; } } catch { status = IntegrationStatus.Exception; throw; } finally { RemoveCompletedRequestFromQueue(); // Tell any extensions that an integration has completed FireIntegrationCompleted(ir, status); // handle post build : check what to do if source control errors occured if (result != null) { if (result.SourceControlError != null) { AmountOfSourceControlExceptions++; } else { AmountOfSourceControlExceptions = 0; } } if ((AmountOfSourceControlExceptions > project.MaxSourceControlRetries) && (project.SourceControlErrorHandling == ThoughtWorks.CruiseControl.Core.Sourcecontrol.Common.SourceControlErrorHandlingPolicy.ReportOnEveryRetryAmount)) { AmountOfSourceControlExceptions = 0; } if ((AmountOfSourceControlExceptions > project.MaxSourceControlRetries) && project.StopProjectOnReachingMaxSourceControlRetries) { Stopped(); } } break; case IntegrationStartedEventArgs.EventResult.Delay: // Log that the request has been cancelled and delay until the request is cleared - otherwise // stuck in an endless loop until the extensions allow the request through Log.Info(string.Format(System.Globalization.CultureInfo.CurrentCulture, "An external extension has delayed an integration - project '{0}' on queue '{1}'", project.Name, project.QueueName)); while (FireIntegrationStarted(ir) == IntegrationStartedEventArgs.EventResult.Delay) { Thread.Sleep(1000); } break; case IntegrationStartedEventArgs.EventResult.Cancel: Log.Info(string.Format(System.Globalization.CultureInfo.CurrentCulture, "An external extension has cancelled an integration - project '{0}' on queue '{1}'", project.Name, project.QueueName)); RemoveCompletedRequestFromQueue(); FireIntegrationCompleted(ir, IntegrationStatus.Cancelled); break; } } } else { PollTriggers(); // If a build is queued for this project we need to hang around until either: // - the build gets started by reaching it's turn on the queue // - the build gets cancelled from the queue // - the thread gets killed // However, if the queue is blocked, do not hang around - we need to exit, so that we can come back to the queue // after the lock has been released (otherwise we could get stuck here forever while (IsRunning && integrationQueue.HasItemPendingOnQueue(project) && !integrationQueue.IsBlocked) { Thread.Sleep(200); } } return(ran); }