Example #1
0
        /// <summary>
        /// Starts the main loop.
        /// </summary>
        /// <param name='primary'>
        /// (Mandatory) Primary Job Consumer, this is the one that will have priority on Job consuption
        /// (e.g. local machine consumer).
        /// </param>
        /// <param name='secundary'>
        /// (Optional) Lower priority consumer.
        /// </param>
        /// <remarks>
        /// THIS BLOCKS EXECUTION! Execute in a thread if you don't want to block the main thread!
        /// Tweak the consumer score to achieve the best performance.
        /// </remarks>
        public void Start(IJobConsumer primary, IJobConsumer secundary)
        {
            Debug.Assert(primary != null);
            if (primary == null)
                throw new ArgumentNullException("You have to set the primary consumer!");

            while (true)
            {
                Job nextJob;
                lock (mQueueLocker)
                {
                    while (mJobQueue.Count == 0)
                        Monitor.Wait(mQueueLocker);

                    nextJob = mJobQueue.Dequeue();
                }

                // We can't get here without Dequeueing at least once!
                if (nextJob == null)
                    break;

                IJobConsumer nextConsumer = null;
                while (nextConsumer == null)
                {
                    if (primary.HasAvailableWorkers)
                    {
                        nextConsumer = primary;
                    }
                    else if (secundary != null && secundary.HasAvailableWorkers)
                    {
                        nextConsumer = secundary;
                    }
                }
                nextConsumer.Consume(nextJob);
            }
        }
Example #2
0
        private static void SetConsumerDelegates(IJobConsumer consumer, JobManager manager, string name)
        {
            consumer.JobStarted += (cons, job) => {
                Console.WriteLine("JOB {0} - Started job {1}", name, job.Id);
            };
            consumer.JobFinished += (cons, job) => {
                Console.WriteLine("JOB {0} - Finished job {1}", name, job.Id);
            };
            // TODO: Add reason to the delegate!
            consumer.JobFailed += (cons, job) => {
                Console.WriteLine("JOB {0} - Failed to consume job {1}", name, job.Id);

                // Add it back to the queue
                manager.EnqueueJob(job);
            };
        }
        async Task RunJob(PipeContext context, IJobConsumer <TJob> jobConsumer)
        {
            var jobContext = context.GetPayload <JobContext <TJob> >();

            RetryPolicyContext <JobContext <TJob> > policyContext = _retryPolicy.CreatePolicyContext(jobContext);

            try
            {
                await jobContext.NotifyStarted().ConfigureAwait(false);

                await jobConsumer.Run(jobContext).ConfigureAwait(false);

                await jobContext.NotifyCompleted().ConfigureAwait(false);
            }
            catch (OperationCanceledException exception)
            {
                if (jobContext.CancellationToken == exception.CancellationToken)
                {
                    await jobContext.NotifyCanceled("Operation canceled").ConfigureAwait(false);
                }
            }
            catch (Exception exception)
            {
                if (!policyContext.CanRetry(exception, out RetryContext <JobContext <TJob> > retryContext))
                {
                    if (_retryPolicy.IsHandled(exception))
                    {
                        context.GetOrAddPayload(() => retryContext);

                        await retryContext.RetryFaulted(exception).ConfigureAwait(false);
                    }

                    await jobContext.NotifyFaulted(exception).ConfigureAwait(false);

                    return;
                }

                var currentRetryAttempt = jobContext.RetryAttempt;
                for (var retryIndex = 0; retryIndex < currentRetryAttempt; retryIndex++)
                {
                    if (!retryContext.CanRetry(exception, out retryContext))
                    {
                        if (_retryPolicy.IsHandled(exception))
                        {
                            context.GetOrAddPayload(() => retryContext);

                            await retryContext.RetryFaulted(exception).ConfigureAwait(false);
                        }

                        await jobContext.NotifyFaulted(exception).ConfigureAwait(false);

                        return;
                    }
                }

                var delay = retryContext.Delay ?? TimeSpan.Zero;

                await jobContext.NotifyFaulted(exception, delay).ConfigureAwait(false);
            }
            finally
            {
                policyContext.Dispose();
            }
        }