Esempio n. 1
0
        private static async Task Start(CancellationToken abortSignal)
        {
            receiveTasks = Enumerable.Range(0, 3).Select(index => DequeueTask(abortSignal)).ToArray();
            var apiTasks = new OptimizedTaskQueue <bool>(log);

            while (!abortSignal.IsCancellationRequested)
            {
                // don't inflate the list if it is already large
                try
                {
                    await WaitForAndHandleEvent(abortSignal, apiTasks);
                }
                catch (Exception e)
                {
                    log.Error(e, "Error waiting for next event");
                }
            }
        }
Esempio n. 2
0
        private static async Task WaitForAndHandleEvent(CancellationToken abortSignal, OptimizedTaskQueue <bool> apiTasks)
        {
            var watchDogCancelToken       = new CancellationTokenSource();
            var watchdogCombinedWithAbort = CancellationTokenSource.CreateLinkedTokenSource(abortSignal, watchDogCancelToken.Token);

            using (watchdogCombinedWithAbort)
                using (watchDogCancelToken)
                {
                    var waitAndListenForCancelTask = Task.Delay(20000, watchdogCombinedWithAbort.Token);
                    var allTasks     = new List <Task>();
                    var firstApiTask = apiTasks.Peek;
                    log.Debug($"awaitable is {firstApiTask?.Id}");
                    if (firstApiTask != null)
                    {
                        allTasks.Add(firstApiTask);
                    }
                    var receiveStart = allTasks.Count;
                    allTasks.AddRange(receiveTasks);
                    var receiveEnd = allTasks.Count;
                    allTasks.Add(waitAndListenForCancelTask);

                    log.Debug($"Waiting for tasks {string.Join(",", allTasks.Select(t => t.Id))}");

                    // TODO make some fault tolerance on exceptions. Best 2-level, first attempt to recover in the code and second with container recycle
                    var task = await Task.WhenAny(allTasks);

                    log.Debug($"when any returned task #{task.Id}");

                    var index = allTasks.IndexOf(task);
                    if (index < 0)
                    {
                        throw new Exception("bad index");
                    }
                    if (index < receiveEnd && index >= receiveStart)
                    {
                        // receiver fired
                        receiveTasks[receiveStart - index] = DequeueTask(abortSignal);
                        watchDogCancelToken.Cancel();
                        apiTasks.Enqueue(AddSomeApiCallTasks(abortSignal));
                    }
                    else if (index == 0)
                    {
                        // api fired
                        watchDogCancelToken.Cancel();
                        apiTasks.Dequeue(firstApiTask);
                    }
                    else
                    {
                        // watchdog timer fired - nothing happened last 20 seconds.
                        return;
                    }
                }
        }