internal JobResultJournalWriter(IObservable <JobResult <TJobInput, TJobOutput> > jobCompletionNotifications, IJobResultInspector <TJobInput, TJobOutput, TQueuePoison> jobResultInspector, IDurableJobQueue <TJobInput, TQueuePoison> durableJobQueue, ILog log, IScheduler scheduler) { if (null == durableJobQueue) { throw new ArgumentNullException("durableJobQueue"); } if (null == jobResultInspector) { throw new ArgumentNullException("jobResultInspector"); } if (null == jobCompletionNotifications) { throw new ArgumentNullException("jobCompletionNotifications"); } this._jobCompleted = jobCompletionNotifications .SubscribeOn(scheduler) .Subscribe(notification => { if (null == notification) { log.Error(CultureInfo.CurrentCulture, m => m("Received invalid NULL Notification<JobResult<{0},{1}>>", typeof(TJobInput).Name, typeof(TJobOutput).Name)); return; } var queueAction = jobResultInspector.Inspect(notification); if (null == queueAction) { log.Error(CultureInfo.CurrentCulture, m => m("Received invalid NULL JobQueueAction<{0}> from Inspect call", typeof(TQueuePoison).Name)); } //no need to check else if (queueAction.ActionType == JobQueueActionType.Poison) { durableJobQueue.Poison(notification.Input, queueAction.QueuePoison); } else if (queueAction.ActionType == JobQueueActionType.Complete) { durableJobQueue.Complete(notification.Input); } else { log.Error(CultureInfo.CurrentCulture, m => m("Received invalid JobQueueAction<{0}> with JobQueueActionType of Unknown", typeof(TQueuePoison).Name)); } }); }
/// <summary> Constructor. </summary> /// <remarks> 7/27/2011. </remarks> /// <exception cref="ArgumentNullException"> Thrown when the durable job queue is null. </exception> /// <param name="durableJobQueue"> IDurableJobQueue to wrap. </param> public ObservableDurableJobQueue(IDurableJobQueue <TQueue, TQueuePoison> durableJobQueue) { if (null == durableJobQueue) { throw new ArgumentNullException("durableJobQueue"); } var queueType = durableJobQueue.GetType(); if (queueType.IsGenericType && typeof(ObservableDurableJobQueue <,>).IsAssignableFrom(queueType.GetGenericTypeDefinition())) { throw new ArgumentException("Incoming queue instance is an ObservableDurableJobQueue. Nesting not supported.", "durableJobQueue"); } this._durableJobQueue = durableJobQueue; }
/// <summary> Constructor for internal uses only -- specifically. </summary> /// <remarks> 7/28/2011. </remarks> /// <exception cref="ArgumentNullException"> Thrown when either the queue or scheduler are null. </exception> /// <exception cref="ArgumentOutOfRangeException"> Thrown when the pollingInterval is below the minimum allowed threshold or greater /// than the maximum allowed threshold. Thrown when the items to publish per interval is /// less than 1 or greater than the maximum allowed threshold. </exception> /// <param name="durableJobQueue"> Queue of durable jobs. </param> /// <param name="maxQueueItemsToPublishPerInterval"> The maximum queue items to publish per interval. </param> /// <param name="pollingInterval"> The polling interval. </param> /// <param name="scheduler"> The scheduler. </param> internal DurableJobQueueMonitor(IDurableJobQueue <TQueue, TQueuePoison> durableJobQueue, int maxQueueItemsToPublishPerInterval, TimeSpan pollingInterval, IScheduler scheduler) { if (null == durableJobQueue) { throw new ArgumentNullException("durableJobQueue"); } if (pollingInterval > DurableJobQueueMonitor.MaximumAllowedPollingInterval) { throw new ArgumentOutOfRangeException("pollingInterval", String.Format(CultureInfo.CurrentCulture, "must be less than {0:c}", DurableJobQueueMonitor. MaximumAllowedPollingInterval.ToString())); } if (pollingInterval < DurableJobQueueMonitor.MinimumAllowedPollingInterval) { throw new ArgumentOutOfRangeException("pollingInterval", String.Format(CultureInfo.CurrentCulture, "must be at least {0:c}", DurableJobQueueMonitor. MinimumAllowedPollingInterval)); } if (maxQueueItemsToPublishPerInterval > DurableJobQueueMonitor.MaxAllowedQueueItemsToPublishPerInterval) { throw new ArgumentOutOfRangeException("maxQueueItemsToPublishPerInterval", String.Format(CultureInfo.CurrentCulture, "limited to {0} items to publish per interval", DurableJobQueueMonitor.MaxAllowedQueueItemsToPublishPerInterval)); } if (maxQueueItemsToPublishPerInterval < 1) { throw new ArgumentOutOfRangeException("maxQueueItemsToPublishPerInterval", "must be at least 1"); } if (null == scheduler) { throw new ArgumentNullException("scheduler"); } this._durableJobQueue = durableJobQueue; this._maxQueueItemsToPublishPerInterval = maxQueueItemsToPublishPerInterval; this._pollingInterval = pollingInterval; //on first construction, we must move any items out of 'pending' and back into 'queued', in the event of a crash recovery, etc durableJobQueue.ResetAllPendingToQueued(); //fire up our polling on an interval, slurping up all non-nulls from 'queued', to a max of X items, but don't start until connect is called _syncRequestPublisher = Observable.Interval(pollingInterval, scheduler) .SelectMany(interval => ReadQueuedItems() .TakeWhile(request => request.Success) .Take(maxQueueItemsToPublishPerInterval)) .Select(item => item.Value) .Publish() .RefCount(); }
protected ReadOnlyCollection <TQueue> SlideItemsToPending(IDurableJobQueue <TQueue, TQueuePoison> jobStorage) { List <TQueue> items = new List <TQueue>(); while (true) { var item = jobStorage.NextQueuedItem(); if (!item.Success) { break; } items.Add(item.Value); } return(new ReadOnlyCollection <TQueue>(items)); }
protected void ClearAllQueues(IDurableJobQueue <TQueue, TQueuePoison> storage) { SlideItemsToPending(storage); Assert.Empty(storage.GetQueued()); foreach (var item in storage.GetPending()) { storage.Complete(item); } Assert.Empty(storage.GetPending()); foreach (var item in storage.GetPoisoned()) { storage.Delete(item); } Assert.Empty(storage.GetPoisoned()); }
public JobResultJournalWriter(IObservable <JobResult <TJobInput, TJobOutput> > jobCompletionNotifications, IJobResultInspector <TJobInput, TJobOutput, TQueuePoison> jobResultInspector, IDurableJobQueue <TJobInput, TQueuePoison> durableJobQueue) : this(jobCompletionNotifications, jobResultInspector, durableJobQueue, LogManager.GetCurrentClassLogger(), LocalScheduler.Default) { }