コード例 #1
0
        internal void AddPendingEvent(PendingEvent ev)
        {
            if (IsShuttingDown) // don't care about adding anything if we're shutting down
            {
                return;
            }

            lock (_lockHeap)
            {
                _eventHeap.Push(ev);
            }
        }
コード例 #2
0
        // returns the index of the added item
        private int Add(PendingEvent ev)
        {
            // check if we need to resize
            if (_events.Length == Count)
            {
                var bigger = new PendingEvent[_events.Length * 2];
                Array.Copy(_events, bigger, Count);
                _events = bigger;
            }

            _events[Count] = ev;
            return(Count++); // postfix is intentional
        }
コード例 #3
0
        public void Push(PendingEvent ev)
        {
            Guard.NotNull(() => ev, ev);
            var ei = Add(ev);

            while (ei > 0)
            {
                var pi = ParentIndex(ei);
                if (ev.IsEarlierThan(_events[pi]))
                {
                    Swap(ei, pi);
                    ei = pi;
                }
                else
                {
                    break;
                }
            }
        }
コード例 #4
0
 internal bool IsEarlierThan(PendingEvent ev)
 {
     return(ScheduledTime < ev.ScheduledTime);
 }
コード例 #5
0
        internal async Task RunPendingEventAsync(PendingEvent ev)
        {
            var eventTime     = ev.ScheduledTime;
            var execLockTaken = false;

            try
            {
                lock (_scheduleLock)
                {
                    if (ev.RunId != _runId)
                    {
                        return;
                    }

                    // take execution lock
                    execLockTaken = Interlocked.CompareExchange(ref _execLocked, 1, 0) == 0;
                    if (execLockTaken)
                    {
                        PrevEvent = eventTime; // set this here while we're still in the schedule lock
                    }
                }

                if (execLockTaken)
                {
                    try
                    {
#if NETFULL
                        var result = _expressionToRun != null ? await _queue.SendAsync(this, eventTime, _expressionToRun).ConfigureAwait(false) : await _queue.SendAsync(this, eventTime, _actionToRun, RawExpression).ConfigureAwait(false);
#else
                        var result = await _queue.SendAsync(this, eventTime, _actionToRun, RawExpression).ConfigureAwait(false);
#endif
                        if (result.Status == JobQueuedStatus.Success || result.Status == JobQueuedStatus.RequeuedDueToErrorStatus)
                        {
                            RaiseEnQueue(result);
                            _queue.Logger.LogDebug($"job {this} queued");
                        }
                        else if (result.Status == JobQueuedStatus.AlreadyQueuedWaiting ||
                                 result.Status == JobQueuedStatus.AlreadyQueuedProcessing ||
                                 result.Status == JobQueuedStatus.AlreadyProcessed)
                        {
                            _queue.Logger.LogWarning($"Failed to enqueue job {this}, the status is {result.Status}");
                            RaiseNonFatalFailureEnQueue(result);
                        }
                        else if (result.SendingException != null)
                        {
                            _queue.Logger.LogError($"An error has occurred adding job {this} into the queue{System.Environment.NewLine}{result.SendingException}");
                            RaiseException(result.SendingException);
                        }
                    }
                    catch (Exception ex)
                    {
                        _queue.Logger.LogError($"A fatal error has occurred trying to add job {this} into the queue{System.Environment.NewLine}{ex}");
                        RaiseException(ex);
                    }
                }
            }
            finally
            {
                if (execLockTaken)
                {
                    _execLocked = 0; // release exec lock
                }
            }

            // figure out the next time to run the schedule
            lock (_scheduleLock)
            {
                if (ev.RunId != _runId)
                {
                    return;
                }

                try
                {
                    var next = Schedule.Next();
                    if (next <= eventTime)
                    {
                        next = Schedule.Next(eventTime);
                    }

                    NextEvent = next;
                    QueueNextEvent();
                }
                catch (Exception ex)
                {
                    _runId++;
                    IsScheduleRunning = false;
                    RaiseException(new DotNetWorkQueueException("Schedule has been terminated because the next valid time could not be found.", ex));
                }
            }
        }
コード例 #6
0
        internal async Task RunPendingEvent(PendingEvent ev)
        {
            var eventTime = ev.ScheduledTime;
            var execLockTaken = false;
            try
            {
                lock (_scheduleLock)
                {
                    if (ev.RunId != _runId)
                        return;

                    // take execution lock
                    execLockTaken = Interlocked.CompareExchange(ref _execLocked, 1, 0) == 0;
                    if (execLockTaken)
                        PrevEvent = eventTime; // set this here while we're still in the schedule lock
                }

                if (execLockTaken)
                {
                    try
                    {
                        var result = _expressionToRun != null ? await _queue.SendAsync(this, eventTime, _expressionToRun).ConfigureAwait(false) : await _queue.SendAsync(this, eventTime, _actionToRun).ConfigureAwait(false);
                        if (result.Status == JobQueuedStatus.Success || result.Status == JobQueuedStatus.RequeuedDueToErrorStatus)
                        {
                            RaiseEnQueue(result);
                            _queue.Logger.Log(LogLevel.Debug, () => $"job {this} has been queued");
                        }
                        else if (result.Status == JobQueuedStatus.AlreadyQueuedWaiting ||
                                 result.Status == JobQueuedStatus.AlreadyQueuedProcessing ||
                                 result.Status == JobQueuedStatus.AlreadyProcessed)
                        {
                            _queue.Logger.Log(LogLevel.Warn, () => $"Failed to enqueue job {this}, the status is {result.Status}");
                            RaiseNonFatalFailtureEnQueue(result);
                        }
                        else if (result.SendingException != null)
                        {
                            _queue.Logger.ErrorException($"An error has occurred adding job {this} into the queue", result.SendingException);
                            RaiseException(result.SendingException);
                        }
                    }
                    catch (Exception ex)
                    {
                        _queue.Logger.ErrorException($"A fatal error has occurred trying to add job {this} into the queue", ex);
                        RaiseException(ex);
                    }
                }
            }
            finally
            {
                if (execLockTaken)
                    _execLocked = 0; // release exec lock
            }

            // figure out the next time to run the schedule
            lock (_scheduleLock)
            {
                if (ev.RunId != _runId)
                    return;

                try
                {
                    var next = Schedule.Next();
                    if (next <= eventTime)
                        next = Schedule.Next(eventTime);

                    NextEvent = next;
                    QueueNextEvent();
                }
                catch (Exception ex)
                {
                    _runId++;
                    IsScheduleRunning = false;
                    RaiseException(new DotNetWorkQueueException("Schedule has been terminated because the next valid time could not be found.", ex));
                }
            }
        }
コード例 #7
0
 internal bool IsEarlierThan(PendingEvent ev)
 {
     return ScheduledTime < ev.ScheduledTime;
 }