private async Task Execute() { try { var cancelToken = _cancellationTokenSource.Token; var opts = new ExecutionDataflowBlockOptions() { MaxDegreeOfParallelism = MaxConcurrentItems, BoundedCapacity = MaxConcurrentItems + 1 }; var actionBlock = new ActionBlock <string>(ExecuteItem, opts); while (!cancelToken.IsCancellationRequested) { try { if (!SpinWait.SpinUntil(() => actionBlock.InputCount == 0, Options.IdleTime)) { continue; } var item = await QueueProvider.DequeueWork(Queue, cancelToken); if (item == null) { if (!QueueProvider.IsDequeueBlocking) { await Task.Delay(Options.IdleTime, cancelToken); } continue; } if (!actionBlock.Post(item)) { await QueueProvider.QueueWork(item, Queue); } } catch (OperationCanceledException ce) { Logger.LogError(ce.Message, ce); } catch (Exception ex) { Logger.LogError(ex.Message, ex); } } actionBlock.Complete(); await actionBlock.Completion; } catch (Exception ex) { Logger.LogError(ex.Message, ex); //This is to prevent async void crashing the program. //Should never reach this line //TODO remove async void } }
private async void RunEvents() { while (!_shutdown) { try { var eventId = await _queueProvider.DequeueWork(QueueType.Event); if (eventId != null) { if (await _lockProvider.AcquireLock($"evt:{eventId}")) { try { var evt = await _persistenceStore.GetEvent(eventId); if (evt.EventTime <= DateTime.Now.ToUniversalTime()) { var subs = await _persistenceStore.GetSubcriptions(evt.EventName, evt.EventKey, evt.EventTime); var success = true; foreach (var sub in subs.ToList()) { success = success && await SeedSubscription(evt, sub); } if (success) { await _persistenceStore.MarkEventProcessed(eventId); } } } catch (Exception ex) { _logger.LogError(ex.Message); } finally { await _lockProvider.ReleaseLock($"evt:{eventId}"); } } else { _logger.LogInformation($"Event locked {eventId}"); } } else { await Task.Delay(_options.IdleTime); //no work } } catch (Exception ex) { _logger.LogError(ex.Message); } } }
private async void Execute() { var cancelToken = _cancellationTokenSource.Token; var activeTasks = new Dictionary <string, Task>(); var secondPasses = new HashSet <string>(); while (!cancelToken.IsCancellationRequested) { try { if (activeTasks.Count >= MaxConcurrentItems) { await Task.Delay(Options.IdleTime); continue; } var item = await QueueProvider.DequeueWork(Queue, cancelToken); if (item == null) { if (!QueueProvider.IsDequeueBlocking) { await Task.Delay(Options.IdleTime, cancelToken); } continue; } if (activeTasks.ContainsKey(item)) { secondPasses.Add(item); if (!EnableSecondPasses) { await QueueProvider.QueueWork(item, Queue); } continue; } secondPasses.Remove(item); var task = new Task(async(object data) => { try { await ExecuteItem((string)data); while (EnableSecondPasses && secondPasses.Contains(item)) { secondPasses.Remove(item); await ExecuteItem((string)data); } } finally { lock (activeTasks) { activeTasks.Remove((string)data); } } }, item); lock (activeTasks) { activeTasks.Add(item, task); } task.Start(); } catch (OperationCanceledException) { } catch (Exception ex) { Logger.LogError(ex, ex.Message); } } foreach (var task in activeTasks.Values) { task.Wait(); } }
private async Task Execute() { var cancelToken = _cancellationTokenSource.Token; while (!cancelToken.IsCancellationRequested) { try { var activeCount = 0; lock (_activeTasks) { activeCount = _activeTasks.Count; } if (activeCount >= MaxConcurrentItems) { await Task.Delay(Options.IdleTime); continue; } var item = await QueueProvider.DequeueWork(Queue, cancelToken); if (item == null) { if (!QueueProvider.IsDequeueBlocking) { await Task.Delay(Options.IdleTime, cancelToken); } continue; } var hasTask = false; lock (_activeTasks) { hasTask = _activeTasks.ContainsKey(item); } if (hasTask) { _secondPasses.Add(item); if (!EnableSecondPasses) { await QueueProvider.QueueWork(item, Queue); } continue; } _secondPasses.TryRemove(item); var waitHandle = new ManualResetEvent(false); lock (_activeTasks) { _activeTasks.Add(item, waitHandle); } var task = ExecuteItem(item, waitHandle); } catch (OperationCanceledException) { } catch (Exception ex) { Logger.LogError(ex, ex.Message); } } List <EventWaitHandle> toComplete; lock (_activeTasks) { toComplete = _activeTasks.Values.ToList(); } foreach (var handle in toComplete) { handle.WaitOne(); } }
/// <summary> /// Worker thread body /// </summary> private async void RunWorkflows() { while (!_shutdown) { try { var workflowId = await _queueProvider.DequeueWork(QueueType.Workflow); if (workflowId != null) { try { if (await _lockProvider.AcquireLock(workflowId)) { WorkflowInstance workflow = null; WorkflowExecutorResult result = null; try { workflow = await _persistenceStore.GetWorkflowInstance(workflowId); if (workflow.Status == WorkflowStatus.Runnable) { try { result = _executor.Execute(workflow, _options); } finally { await _persistenceStore.PersistWorkflow(workflow); } } } finally { await _lockProvider.ReleaseLock(workflowId); if ((workflow != null) && (result != null)) { foreach (var sub in result.Subscriptions) { await SubscribeEvent(sub); } await _persistenceStore.PersistErrors(result.Errors); if ((workflow.Status == WorkflowStatus.Runnable) && workflow.NextExecution.HasValue && workflow.NextExecution.Value < DateTime.Now.ToUniversalTime().Ticks) { await _queueProvider.QueueWork(workflowId, QueueType.Workflow); } } } } else { _logger.LogInformation("Workflow locked {0}", workflowId); } } catch (Exception ex) { _logger.LogError(ex.Message); } } else { await Task.Delay(_options.IdleTime); //no work } } catch (Exception ex) { _logger.LogError(ex.Message); } } }