Example #1
0
        /// <summary>
        /// Get the certificates, if not from cache then from the server
        /// </summary>
        /// <param name="orderContexts"></param>
        /// <param name="runLevel"></param>
        /// <returns></returns>
        private async Task ExecuteOrders(List <OrderContext> orderContexts, RunLevel runLevel)
        {
            foreach (var order in orderContexts)
            {
                // Get the previously issued certificates in this renewal
                // sub order regardless of the fact that it may have another
                // shape (e.g. different SAN names or common name etc.). This
                // means we cannot use the cache key for it.
                order.PreviousCertificate = _certificateService.
                                            CachedInfos(order.Renewal, order.Order).
                                            OrderByDescending(x => x.Certificate.NotBefore).
                                            FirstOrDefault();

                if (order.PreviousCertificate == null)
                {
                    // Fallback to legacy cache file name without
                    // order name part
                    order.PreviousCertificate = _certificateService.
                                                CachedInfos(order.Renewal).
                                                Where(c => !orderContexts.Any(o => c.CacheFile !.Name.Contains($"-{o.Order.CacheKeyPart ?? "main"}-"))).
                                                OrderByDescending(x => x.Certificate.NotBefore).
                                                FirstOrDefault();
                }

                // Get the existing certificate matching the order description
                // this may not be the same as the previous certificate
                order.NewCertificate = GetFromCache(order, runLevel);
            }

            // Group validations of multiple order together
            // as to maximize the potential gains in parallelization
            var fromServer = orderContexts.Where(x => x.NewCertificate == null).ToList();

            foreach (var order in fromServer)
            {
                await CreateOrder(order);
            }

            // Validate all orders that need it
            var alwaysTryValidation = runLevel.HasFlag(RunLevel.Test) || runLevel.HasFlag(RunLevel.IgnoreCache);
            var validationRequired  = fromServer.Where(x => x.Order.Details != null && (x.Order.Valid == false || alwaysTryValidation));
            await _validator.AuthorizeOrders(validationRequired, runLevel);

            // Download all the orders in parallel
            await Task.WhenAll(orderContexts.Select(async order =>
            {
                if (order.Result.Success == false)
                {
                    _log.Verbose("Order {n}/{m} ({friendly}): validation error",
                                 orderContexts.IndexOf(order) + 1,
                                 orderContexts.Count,
                                 order.OrderName);
                }
                else if (order.NewCertificate == null)
                {
                    _log.Verbose("Order {n}/{m} ({friendly}): processing...",
                                 orderContexts.IndexOf(order) + 1,
                                 orderContexts.Count,
                                 order.OrderName);
                    order.NewCertificate = await GetFromServer(order);
                }
                else
                {
                    _log.Verbose("Order {n}/{m} ({friendly}): handle from cache",
                                 orderContexts.IndexOf(order) + 1,
                                 orderContexts.Count,
                                 order.OrderName);
                }
            }));
        }