/// <inheritdoc /> public async Task <IJobQueueOutputMessage> SendAsync(IScheduledJob job, DateTimeOffset scheduledTime, Expression <Action <IReceivedMessage <MessageExpression>, IWorkerNotification> > method, bool rawExpression = false) { using (IScope scope = _tracer.BuildSpan("SendJobAsync").StartActive(finishSpanOnDispose: true)) { scope.Span.SetTag("JobName", job.Name); return(await _handler.SendAsync(job, scheduledTime, method, rawExpression)); } }
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)); } } }