public override async Task <IQueueEntry <T> > DequeueAsync(CancellationToken cancellationToken) { _logger.Trace("Queue {type} dequeuing item...", typeof(T).Name); _logger.Trace("Queue count: {0}", _queue.Count); if (_queue.Count == 0 && !cancellationToken.IsCancellationRequested) { _logger.Trace("Waiting to dequeue item..."); var sw = Stopwatch.StartNew(); try { using (await _monitor.EnterAsync(cancellationToken)) await _monitor.WaitAsync(cancellationToken).AnyContext(); } catch (TaskCanceledException) {} sw.Stop(); _logger.Trace("Waited for dequeue: {0}", sw.Elapsed.ToString()); } if (_queue.Count == 0) { return(null); } _logger.Trace("Dequeue: Attempt"); QueueEntry <T> info; if (!_queue.TryDequeue(out info) || info == null) { return(null); } info.Attempts++; info.DequeuedTimeUtc = DateTime.UtcNow; if (!_dequeued.TryAdd(info.Id, info)) { throw new ApplicationException("Unable to add item to the dequeued list."); } Interlocked.Increment(ref _dequeuedCount); _logger.Trace("Dequeue: Got Item"); var entry = new QueueEntry <T>(info.Id, info.Value.Copy(), this, info.EnqueuedTimeUtc, info.Attempts); await OnDequeuedAsync(entry).AnyContext(); ScheduleNextMaintenance(DateTime.UtcNow.Add(_workItemTimeout)); return(entry); }
public override void StartWorking(Func <QueueEntry <T>, CancellationToken, Task> handler, bool autoComplete = false, CancellationToken cancellationToken = default(CancellationToken)) { if (handler == null) { throw new ArgumentNullException(nameof(handler)); } Logger.Trace().Message("Queue {0} start working", typeof(T).Name).Write(); var linkedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(_disposeTokenSource.Token, cancellationToken).Token; Task.Run(async() => { #if DEBUG Logger.Trace().Message("WorkerLoop Start {0}", typeof(T).Name).Write(); #endif while (!linkedCancellationToken.IsCancellationRequested) { #if DEBUG Logger.Trace().Message("WorkerLoop Signaled {0}", typeof(T).Name).Write(); #endif QueueEntry <T> queueEntry = null; try { queueEntry = await DequeueAsync(cancellationToken: cancellationToken).AnyContext(); } catch (Exception ex) { Logger.Error().Message("Error on Dequeue: " + ex.Message).Exception(ex).Write(); } if (queueEntry == null) { return; } try { await handler(queueEntry, linkedCancellationToken).AnyContext(); if (autoComplete) { await queueEntry.CompleteAsync().AnyContext(); } } catch (Exception ex) { Logger.Error().Exception(ex).Message("Worker error: {0}", ex.Message).Write(); await queueEntry.AbandonAsync().AnyContext(); Interlocked.Increment(ref _workerErrorCount); } } #if DEBUG Logger.Trace().Message("WorkLoop End").Write(); #endif }, linkedCancellationToken); }
protected override async Task <IQueueEntry <T> > DequeueImplAsync(CancellationToken linkedCancellationToken) { _logger.Trace("Queue {type} dequeuing item...", _options.Name); _logger.Trace("Queue count: {0}", _queue.Count); while (_queue.Count == 0 && !linkedCancellationToken.IsCancellationRequested) { _logger.Trace("Waiting to dequeue item..."); var sw = Stopwatch.StartNew(); try { await _autoResetEvent.WaitAsync(GetDequeueCanncellationToken(linkedCancellationToken)).AnyContext(); } catch (OperationCanceledException) { } sw.Stop(); _logger.Trace("Waited for dequeue: {0}", sw.Elapsed.ToString()); } if (_queue.Count == 0) { return(null); } _logger.Trace("Dequeue: Attempt"); if (!_queue.TryDequeue(out QueueEntry <T> info) || info == null) { return(null); } info.Attempts++; info.DequeuedTimeUtc = SystemClock.UtcNow; if (!_dequeued.TryAdd(info.Id, info)) { throw new Exception("Unable to add item to the dequeued list."); } Interlocked.Increment(ref _dequeuedCount); _logger.Trace("Dequeue: Got Item"); var entry = new QueueEntry <T>(info.Id, info.Value.DeepClone(), this, info.EnqueuedTimeUtc, info.Attempts); await entry.RenewLockAsync(); await OnDequeuedAsync(entry).AnyContext(); ScheduleNextMaintenance(SystemClock.UtcNow.Add(_options.WorkItemTimeout)); return(entry); }
private async Task <IQueueEntry <T> > HandleDequeueAsync(BrokeredMessage msg) { if (msg == null) { return(null); } var data = msg.GetBody <T>(); Interlocked.Increment(ref _dequeuedCount); var entry = new QueueEntry <T>(msg.LockToken.ToString(), data, this, msg.EnqueuedTimeUtc, msg.DeliveryCount); await OnDequeuedAsync(entry).AnyContext(); return(entry); }
private async Task <IQueueEntry <T> > HandleDequeueAsync(BrokeredMessage brokeredMessage) { if (brokeredMessage == null) { return(null); } var message = _serializer.Deserialize <T>(brokeredMessage.GetBody <Stream>()); Interlocked.Increment(ref _dequeuedCount); var entry = new QueueEntry <T>(brokeredMessage.LockToken.ToString(), message, this, brokeredMessage.EnqueuedTimeUtc, brokeredMessage.DeliveryCount); await OnDequeuedAsync(entry).AnyContext(); return(entry); }
public override async Task <QueueEntry <T> > DequeueAsync(CancellationToken cancellationToken = default(CancellationToken)) { // TODO: use the cancellation token. using (var msg = await _queueClient.ReceiveAsync().AnyContext()) { if (msg == null) { return(null); } var data = msg.GetBody <T>(); Interlocked.Increment(ref _dequeuedCount); var entry = new QueueEntry <T>(msg.LockToken.ToString(), data, this, msg.EnqueuedTimeUtc, msg.DeliveryCount); await OnDequeuedAsync(entry).AnyContext(); return(entry); } }
public override async Task CompleteAsync(IQueueEntry <T> entry) { _logger.Trace("Queue {0} complete item: {1}", typeof(T).Name, entry.Id); QueueEntry <T> info = null; if (!_dequeued.TryRemove(entry.Id, out info) || info == null) { throw new ApplicationException("Unable to remove item from the dequeued list."); } Interlocked.Increment(ref _completedCount); await OnCompletedAsync(entry).AnyContext(); _logger.Trace("Complete done: {0}", entry.Id); }
private async Task <IQueueEntry <T> > HandleDequeueAsync(Message brokeredMessage) { if (brokeredMessage == null) { return(null); } var message = _serializer.Deserialize <T>(brokeredMessage.Body); Interlocked.Increment(ref _dequeuedCount); var entry = new QueueEntry <T>(brokeredMessage.SystemProperties.LockToken, message, this, brokeredMessage.ScheduledEnqueueTimeUtc, brokeredMessage.SystemProperties.DeliveryCount); await OnDequeuedAsync(entry).AnyContext(); return(entry); }
protected override async Task <string> EnqueueImplAsync(T data) { if (!await OnEnqueuingAsync(data).AnyContext()) { return(null); } Interlocked.Increment(ref _enqueuedCount); var message = new BrokeredMessage(data); await _queueClient.SendAsync(message).AnyContext(); var entry = new QueueEntry <T>(message.MessageId, data, this, SystemClock.UtcNow, 0); await OnEnqueuedAsync(entry).AnyContext(); return(message.MessageId); }
public override async Task <string> EnqueueAsync(T data) { if (!await OnEnqueuingAsync(data).AnyContext()) { return(null); } Interlocked.Increment(ref _enqueuedCount); var message = new CloudQueueMessage(await _serializer.SerializeAsync(data)); await _queueReference.AddMessageAsync(message).AnyContext(); var entry = new QueueEntry <T>(message.Id, data, this, DateTime.UtcNow, 0); await OnEnqueuedAsync(entry).AnyContext(); return(message.Id); }
protected override async Task <string> EnqueueImplAsync(T data) { if (!await OnEnqueuingAsync(data).AnyContext()) { return(null); } Interlocked.Increment(ref _enqueuedCount); var message = CloudQueueMessage.CreateCloudQueueMessageFromByteArray(_serializer.SerializeToBytes(data)); await _queueReference.AddMessageAsync(message).AnyContext(); var entry = new QueueEntry <T>(message.Id, data, this, SystemClock.UtcNow, 0); await OnEnqueuedAsync(entry).AnyContext(); return(message.Id); }
public override void StartWorking(Func <QueueEntry <T>, CancellationToken, Task> handler, bool autoComplete = false, CancellationToken cancellationToken = default(CancellationToken)) { if (handler == null) { throw new ArgumentNullException(nameof(handler)); } var linkedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(_queueDisposedCancellationTokenSource.Token, cancellationToken).Token; Task.Run(async() => { #if DEBUG Logger.Trace().Message($"WorkerLoop Start {_queueName}").Write(); #endif while (!linkedCancellationToken.IsCancellationRequested) { #if DEBUG Logger.Trace().Message($"WorkerLoop Pass {_queueName}").Write(); #endif QueueEntry <T> queueEntry = null; try { queueEntry = await DequeueAsync(cancellationToken: cancellationToken).AnyContext(); } catch (TimeoutException) { } if (linkedCancellationToken.IsCancellationRequested || queueEntry == null) { continue; } try { await handler(queueEntry, linkedCancellationToken).AnyContext(); if (autoComplete) { await queueEntry.CompleteAsync().AnyContext(); } } catch (Exception ex) { Logger.Error().Exception(ex).Message("Worker error: {0}", ex.Message).Write(); await queueEntry.AbandonAsync().AnyContext(); Interlocked.Increment(ref _workerErrorCount); } } #if DEBUG Logger.Trace().Message("Worker exiting: {0} Cancel Requested: {1}", _queueName, linkedCancellationToken.IsCancellationRequested).Write(); #endif }, linkedCancellationToken); }
protected override async Task <string> EnqueueImplAsync(T data, QueueEntryOptions options) { string id = Guid.NewGuid().ToString("N"); _logger.LogTrace("Queue {Name} enqueue item: {Id}", _options.Name, id); if (!await OnEnqueuingAsync(data, options).AnyContext()) { return(null); } var entry = new QueueEntry <T>(id, options?.CorrelationId, data.DeepClone(), this, SystemClock.UtcNow, 0); entry.Properties.AddRange(options?.Properties); Interlocked.Increment(ref _enqueuedCount); if (options?.DeliveryDelay != null && options.DeliveryDelay.Value > TimeSpan.Zero) { _ = Run.DelayedAsync(options.DeliveryDelay.Value, async() => { _queue.Enqueue(entry); _logger.LogTrace("Enqueue: Set Event"); _autoResetEvent.Set(); await OnEnqueuedAsync(entry).AnyContext(); _logger.LogTrace("Enqueue done"); }, _queueDisposedCancellationTokenSource.Token); return(id); } _queue.Enqueue(entry); _logger.LogTrace("Enqueue: Set Event"); _autoResetEvent.Set(); await OnEnqueuedAsync(entry).AnyContext(); _logger.LogTrace("Enqueue done"); return(id); }
private async Task <IQueueEntry <T> > HandleDequeueAsync(Message brokeredMessage) { if (brokeredMessage == null) { return(null); } var message = _serializer.Deserialize <T>(brokeredMessage.Body); Interlocked.Increment(ref _dequeuedCount); var entry = new QueueEntry <T>(brokeredMessage.MessageId, brokeredMessage.CorrelationId, message, this, brokeredMessage.SystemProperties.EnqueuedTimeUtc, brokeredMessage.SystemProperties.DeliveryCount); foreach (var property in brokeredMessage.UserProperties) { entry.Properties.Add(property.Key, property.Value); } await OnDequeuedAsync(entry).AnyContext(); return(entry); }
protected override async Task <string> EnqueueImplAsync(T data) { if (!await OnEnqueuingAsync(data).AnyContext()) { return(null); } Interlocked.Increment(ref _enqueuedCount); var stream = new MemoryStream(); _serializer.Serialize(data, stream); var brokeredMessage = new BrokeredMessage(stream, true); await _queueClient.SendAsync(brokeredMessage).AnyContext(); // TODO: See if there is a way to send a batch of messages. var entry = new QueueEntry <T>(brokeredMessage.MessageId, data, this, SystemClock.UtcNow, 0); await OnEnqueuedAsync(entry).AnyContext(); return(brokeredMessage.MessageId); }
protected override async Task <string> EnqueueImplAsync(T data) { if (!await OnEnqueuingAsync(data).AnyContext()) { return(null); } var message = new SendMessageRequest { QueueUrl = _queueUrl, MessageBody = await _serializer.SerializeToStringAsync(data).AnyContext(), }; var response = await _client.Value.SendMessageAsync(message).AnyContext(); Interlocked.Increment(ref _enqueuedCount); var entry = new QueueEntry <T>(response.MessageId, data, this, SystemClock.UtcNow, 0); await OnEnqueuedAsync(entry).AnyContext(); return(response.MessageId); }
protected override async Task <string> EnqueueImplAsync(T data, QueueEntryOptions options) { if (!await OnEnqueuingAsync(data, options).AnyContext()) { return(null); } var message = new SendMessageRequest { QueueUrl = _queueUrl, MessageBody = _serializer.SerializeToString(data) }; if (!String.IsNullOrEmpty(options?.CorrelationId)) { message.MessageAttributes.Add("CorrelationId", new MessageAttributeValue { DataType = "String", StringValue = options.CorrelationId }); } if (options?.Properties != null) { foreach (var property in options.Properties) { message.MessageAttributes.Add(property.Key, new MessageAttributeValue { DataType = "String", StringValue = property.Value.ToString() // TODO: Support more than string data types }); } } var response = await _client.Value.SendMessageAsync(message).AnyContext(); Interlocked.Increment(ref _enqueuedCount); var entry = new QueueEntry <T>(response.MessageId, options?.CorrelationId, data, this, SystemClock.UtcNow, 0); await OnEnqueuedAsync(entry).AnyContext(); return(response.MessageId); }
protected override async Task <string> EnqueueImplAsync(T data) { string id = Guid.NewGuid().ToString("N"); _logger.Debug("Queue {_queueName} enqueue item: {id}", _queueName, id); if (!await OnEnqueuingAsync(data).AnyContext()) { _logger.Trace("Aborting enqueue item: {id}", id); return(null); } var now = SystemClock.UtcNow; bool success = await Run.WithRetriesAsync(() => _cache.AddAsync(GetPayloadKey(id), data, _payloadTtl), logger : _logger).AnyContext(); if (!success) { throw new InvalidOperationException("Attempt to set payload failed."); } await Run.WithRetriesAsync(() => _cache.SetAsync(GetEnqueuedTimeKey(id), now.Ticks, _payloadTtl), logger : _logger).AnyContext(); await Run.WithRetriesAsync(() => Database.ListLeftPushAsync(QueueListName, id), logger : _logger).AnyContext(); // This should pulse the monitor. try { await Run.WithRetriesAsync(() => _subscriber.PublishAsync(GetTopicName(), id), logger : _logger).AnyContext(); } catch { } Interlocked.Increment(ref _enqueuedCount); var entry = new QueueEntry <T>(id, data, this, now, 0); await OnEnqueuedAsync(entry).AnyContext(); _logger.Trace("Enqueue done"); return(id); }
protected override async Task <string> EnqueueImplAsync(T data, QueueEntryOptions options) { string id = Guid.NewGuid().ToString("N"); bool isTraceLogLevelEnabled = _logger.IsEnabled(LogLevel.Trace); if (isTraceLogLevelEnabled) { _logger.LogTrace("Queue {Name} enqueue item: {Id}", _options.Name, id); } if (!await OnEnqueuingAsync(data, options).AnyContext()) { return(null); } var entry = new QueueEntry <T>(id, options?.CorrelationId, data.DeepClone(), this, SystemClock.UtcNow, 0); entry.Properties.AddRange(options?.Properties); _queue.Enqueue(entry); if (isTraceLogLevelEnabled) { _logger.LogTrace("Enqueue: Set Event"); } _autoResetEvent.Set(); Interlocked.Increment(ref _enqueuedCount); await OnEnqueuedAsync(entry).AnyContext(); if (isTraceLogLevelEnabled) { _logger.LogTrace("Enqueue done"); } return(id); }
private Task WorkerLoop(CancellationToken token) { Log.Trace().Message("WorkerLoop Start {0}", typeof(T).Name).Write(); while (!token.IsCancellationRequested) { if (_queue.Count == 0 || _workerAction == null) { _autoEvent.WaitOne(TimeSpan.FromMilliseconds(250)); } Log.Trace().Message("WorkerLoop Signaled {0}", typeof(T).Name).Write(); QueueEntry <T> queueEntry = null; try { queueEntry = Dequeue(TimeSpan.Zero); } catch (TimeoutException) { } if (queueEntry == null || _workerAction == null) { return(TaskHelper.Completed()); } try { _workerAction(queueEntry); if (_workerAutoComplete) { queueEntry.Complete(); } } catch (Exception ex) { Log.Error().Exception(ex).Message("Worker error: {0}", ex.Message).Write(); queueEntry.Abandon(); Interlocked.Increment(ref _workerErrorCount); } } return(TaskHelper.Completed()); }
public override async Task <QueueEntry <T> > DequeueAsync(CancellationToken cancellationToken = default(CancellationToken)) { #if DEBUG Logger.Trace().Message($"Queue {_queueName} dequeuing item...").Write(); #endif await EnsureMaintenanceRunningAsync().AnyContext(); await EnsureTopicSubscriptionAsync().AnyContext(); var linkedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(_queueDisposedCancellationTokenSource.Token, cancellationToken).Token; RedisValue value = await GetRedisValueAsync(linkedCancellationToken).AnyContext(); if (linkedCancellationToken.IsCancellationRequested && value.IsNullOrEmpty) { return(null); } #if DEBUG Logger.Trace().Message("Initial list value: {0}", (value.IsNullOrEmpty ? "<null>" : value.ToString())).Write(); #endif while (value.IsNullOrEmpty && !linkedCancellationToken.IsCancellationRequested) { #if DEBUG Logger.Trace().Message("Waiting to dequeue item...").Write(); var sw = Stopwatch.StartNew(); #endif try { using (await _monitor.EnterAsync(cancellationToken)) await _monitor.WaitAsync(cancellationToken).AnyContext(); } catch (TaskCanceledException) { } #if DEBUG sw.Stop(); Logger.Trace().Message("Waited for dequeue: {0}", sw.Elapsed.ToString()).Write(); #endif value = await GetRedisValueAsync(linkedCancellationToken).AnyContext(); #if DEBUG Logger.Trace().Message("List value: {0}", (value.IsNullOrEmpty ? "<null>" : value.ToString())).Write(); #endif } if (value.IsNullOrEmpty) { return(null); } await _cache.SetAsync(GetDequeuedTimeKey(value), DateTime.UtcNow.Ticks, GetDequeuedTimeTtl()).AnyContext(); try { var payload = await _cache.GetAsync <T>(GetPayloadKey(value)).AnyContext(); if (payload.IsNull) { Logger.Error().Message("Error getting queue payload: {0}", value).Write(); await _db.ListRemoveAsync(WorkListName, value).AnyContext(); return(null); } var enqueuedTimeTicks = await _cache.GetAsync <long>(GetEnqueuedTimeKey(value), 0).AnyContext(); var attemptsValue = await _cache.GetAsync <int>(GetAttemptsKey(value), -1).AnyContext(); var entry = new QueueEntry <T>(value, payload.Value, this, new DateTime(enqueuedTimeTicks, DateTimeKind.Utc), attemptsValue); Interlocked.Increment(ref _dequeuedCount); await OnDequeuedAsync(entry).AnyContext(); #if DEBUG Logger.Debug().Message("Dequeued item: {0}", value).Write(); #endif return(entry); } catch (Exception ex) { Logger.Error().Exception(ex).Message("Error getting queue payload: {0}", value).Write(); throw; } }
protected override async Task <IQueueEntry <T> > DequeueImplAsync(CancellationToken linkedCancellationToken) { bool isTraceLogLevelEnabled = _logger.IsEnabled(LogLevel.Trace); if (isTraceLogLevelEnabled) { _logger.LogTrace("Queue {Name} dequeuing item... Queue count: {Count}", _options.Name, _queue.Count); } while (_queue.Count == 0 && !linkedCancellationToken.IsCancellationRequested) { if (isTraceLogLevelEnabled) { _logger.LogTrace("Waiting to dequeue item..."); } var sw = Stopwatch.StartNew(); try { using (var timeoutCancellationTokenSource = new CancellationTokenSource(10000)) using (var dequeueCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(linkedCancellationToken, timeoutCancellationTokenSource.Token)) { await _autoResetEvent.WaitAsync(dequeueCancellationTokenSource.Token).AnyContext(); } } catch (OperationCanceledException) { } sw.Stop(); if (isTraceLogLevelEnabled) { _logger.LogTrace("Waited for dequeue: {Elapsed:g}", sw.Elapsed); } } if (_queue.Count == 0) { return(null); } if (isTraceLogLevelEnabled) { _logger.LogTrace("Dequeue: Attempt"); } if (!_queue.TryDequeue(out var info) || info == null) { return(null); } info.Attempts++; info.DequeuedTimeUtc = SystemClock.UtcNow; if (!_dequeued.TryAdd(info.Id, info)) { throw new Exception("Unable to add item to the dequeued list."); } Interlocked.Increment(ref _dequeuedCount); if (isTraceLogLevelEnabled) { _logger.LogTrace("Dequeue: Got Item"); } var entry = new QueueEntry <T>(info.Id, info.Value.DeepClone(), this, info.EnqueuedTimeUtc, info.Attempts); await entry.RenewLockAsync(); await OnDequeuedAsync(entry).AnyContext(); ScheduleNextMaintenance(SystemClock.UtcNow.Add(_options.WorkItemTimeout)); return(entry); }
private async Task RetryAsync(QueueEntry <T> entry) { _queue.Enqueue(entry); using (await _monitor.EnterAsync()) _monitor.Pulse(); }