/// <summary>
        /// Called once at startup by the hosting infrastructure. This function must remain running
        /// for the entire lifetime of an application.
        /// </summary>
        /// <param name="cancellationToken">Indicates when the web application is shutting down.</param>
        /// <returns>The Task representing the async function results.</returns>
        public override async Task RunAsync(CancellationToken cancellationToken)
        {
            // First wait for all informers to fully List resources before processing begins.
            foreach (var registration in _registrations)
            {
                await registration.ReadyAsync(cancellationToken).ConfigureAwait(false);
            }

            // At this point we know that all of the Ingress and Endpoint caches are at least in sync
            // with cluster's state as of the start of this controller.

            // Now begin one loop to process work until an application shudown is requested.
            while (!cancellationToken.IsCancellationRequested)
            {
                // Dequeue the next item to process
                var(item, shutdown) = await _queue.GetAsync(cancellationToken).ConfigureAwait(false);

                if (shutdown)
                {
                    return;
                }

                try
                {
                    // Fetch the currently known information about this Ingress
                    if (_cache.TryGetReconcileData(item.NamespacedName, out var data))
                    {
#pragma warning disable CA1303 // Do not pass literals as localized parameters
                        Logger.LogInformation("Processing {IngressNamespace} {IngressName}", item.NamespacedName.Namespace, item.NamespacedName.Name);
#pragma warning restore CA1303 // Do not pass literals as localized parameters

                        // Pass the information to the reconciler to process and dispatch
                        await _reconciler.ProcessAsync(item.DispatchTarget, item.NamespacedName, data, cancellationToken).ConfigureAwait(false);
                    }

                    // Tell the queue to forget any exponential backoff details like attempt count
                    _queue.Forget(item);
                }
#pragma warning disable CA1031 // Do not catch general exception types
                catch
#pragma warning restore CA1031 // Do not catch general exception types
                {
#pragma warning disable CA1303 // Do not pass literals as localized parameters
                    Logger.LogInformation("Rescheduling {IngressNamespace} {IngressName}", item.NamespacedName.Namespace, item.NamespacedName.Name);
#pragma warning restore CA1303 // Do not pass literals as localized parameters

                    // Any failure to process this item results in being re-queued after
                    // a per-item exponential backoff delay combined with
                    // and an overall retry rate of 10 per second
                    _queue.AddRateLimited(item);
                }
                finally
                {
                    // calling Done after GetAsync informs the queue
                    // that the item is no longer being actively processed
                    _queue.Done(item);
                }
            }
        }
Example #2
0
 /// <inheritdoc/>
 public virtual void Forget(TItem item) => _base.Forget(item);