public void HandleJobs(List <EnterspeedJob> jobs)
        {
            if (!jobs.Any())
            {
                return;
            }

            LogHelper.Debug <EnterspeedJobHandler>("Handling {jobsCount} jobs", () => jobs.Count);

            // Update jobs from pending to processing
            foreach (var job in jobs)
            {
                job.State     = EnterspeedJobState.Processing;
                job.UpdatedAt = DateTime.UtcNow;
            }

            _enterspeedJobRepository.Save(jobs);

            // Process nodes
            var failedJobs         = new List <EnterspeedJob>();
            var failedJobsToDelete = new List <EnterspeedJob>();

            // Get a dictionary of contentid and cultures to handle
            var jobsToHandle = jobs
                               .Select(x => x.ContentId)
                               .Distinct()
                               .ToDictionary(x => x, x => jobs.Where(j => j.ContentId == x).Select(j => j.Culture).Distinct().ToList());

            // Fetch all failed jobs for these content ids. We need to do this to delete the failed jobs if they no longer fails
            var failedJobsToHandle = _enterspeedJobRepository.GetFailedJobs(jobs.Select(x => x.ContentId).Distinct().ToList());
            var context            = UmbracoContextHelper.GetUmbracoContext();

            foreach (var jobInfo in jobsToHandle)
            {
                foreach (var culture in jobInfo.Value)
                {
                    // List of all jobs with this contentid and culture
                    var jobsToRun = jobs
                                    .Where(x => x.ContentId == jobInfo.Key && x.Culture == culture)
                                    .OrderBy(x => x.CreatedAt)
                                    .ToList();

                    // Get the failed jobs and add it to the batch of jobs that needs to be handled, so we can delete them afterwards
                    failedJobsToDelete.AddRange(failedJobsToHandle.Where(x =>
                                                                         x.ContentId == jobInfo.Key && x.Culture == culture));

                    // We only need to execute the latest jobs instruction.
                    var newestJob     = jobsToRun.LastOrDefault();
                    var shouldDelete  = newestJob?.JobType == EnterspeedJobType.Delete;
                    var shouldPublish = newestJob?.JobType == EnterspeedJobType.Publish;

                    if (shouldPublish)
                    {
                        var content = context.ContentCache.GetById(newestJob.ContentId);
                        if (content == null)
                        {
                            // Create a new failed job
                            var exception = $"Content with id {newestJob.ContentId} not in cache";
                            failedJobs.Add(GetFailedJob(newestJob, exception));
                            LogHelper.Warn <EnterspeedJobHandler>(exception);
                            continue;
                        }

                        // Create Umbraco Enterspeed Entity
                        UmbracoContentEntity umbracoData;
                        try
                        {
                            umbracoData = new UmbracoContentEntity(content);
                        }
                        catch (Exception e)
                        {
                            // Create a new failed job
                            var exception = $"Failed creating entity ({newestJob.ContentId}/{newestJob.Culture}). Message: {e.Message}. StackTrace: {e.StackTrace}";
                            failedJobs.Add(GetFailedJob(newestJob, exception));
                            LogHelper.Warn <EnterspeedJobHandler>(exception);
                            continue;
                        }

                        var ingestResponse = _enterspeedIngestService.Save(umbracoData);
                        if (!ingestResponse.Success)
                        {
                            // Create a new failed job
                            var message = ingestResponse.Exception != null
                                ? ingestResponse.Exception.Message
                                : ingestResponse.Message;

                            var exception =
                                $"Failed ingesting entity ({newestJob.ContentId}/{newestJob.Culture}). Message: {message}";
                            failedJobs.Add(GetFailedJob(newestJob, exception));
                            LogHelper.Warn <EnterspeedJobHandler>(exception);
                        }
                    }
                    else if (shouldDelete)
                    {
                        var id             = _entityIdentityService.GetId(newestJob.ContentId);
                        var deleteResponse = _enterspeedIngestService.Delete(id);
                        if (!deleteResponse.Success && deleteResponse.Status != HttpStatusCode.NotFound)
                        {
                            // Create a new failed job
                            var exception = $"Failed deleting entity ({newestJob.ContentId}/{newestJob.Culture}). Message: {deleteResponse.Message}";
                            failedJobs.Add(GetFailedJob(newestJob, exception));
                            LogHelper.Warn <EnterspeedJobHandler>(exception);
                            continue;
                        }
                    }
                }
            }

            // Save all jobs that failed
            _enterspeedJobRepository.Save(failedJobs);

            // Delete all jobs - Note, that it's safe to delete all jobs because failed jobs will be created as a new job
            _enterspeedJobRepository.Delete(jobs.Select(x => x.Id).Concat(failedJobsToDelete.Select(x => x.Id)).ToList());

            // Throw exception with a combined exception message for all jobs that failed if any
            if (failedJobs.Any())
            {
                var failedJobExceptions = string.Join(Environment.NewLine, failedJobs.Select(x => x.Exception));
                throw new Exception(failedJobExceptions);
            }
        }
Ejemplo n.º 2
0
        private void HandleContentItem(Item item, EnterspeedSitecoreConfiguration configuration, bool itemIsDeleted, bool itemIsPublished)
        {
            try
            {
                if (item == null)
                {
                    return;
                }

                // Skip, if the item published is not a content item
                if (!item.IsContentItem())
                {
                    return;
                }

                EnterspeedSiteInfo siteOfItem = configuration.GetSite(item);
                if (siteOfItem == null)
                {
                    // If no enabled site was found for this item, skip it
                    return;
                }

                SitecoreContentEntity sitecoreContentEntity = _sitecoreContentEntityModelMapper.Map(item);
                if (sitecoreContentEntity == null)
                {
                    return;
                }

                if (itemIsDeleted)
                {
                    string id = _identityService.GetId(item);
                    _loggingService.Info($"Beginning to delete content entity ({id}).");
                    Response deleteResponse = _enterspeedIngestService.Delete(id);

                    if (!deleteResponse.Success)
                    {
                        _loggingService.Warn($"Failed deleting content entity ({id}). Message: {deleteResponse.Message}", deleteResponse.Exception);
                    }
                    else
                    {
                        _loggingService.Debug($"Successfully deleting content entity ({id})");
                    }

                    return;
                }

                if (itemIsPublished)
                {
                    string id = _identityService.GetId(item);
                    _loggingService.Info($"Beginning to ingest content entity ({id}).");
                    Response saveResponse = _enterspeedIngestService.Save(sitecoreContentEntity);

                    if (!saveResponse.Success)
                    {
                        _loggingService.Warn($"Failed ingesting content entity ({id}). Message: {saveResponse.Message}", saveResponse.Exception);
                    }
                    else
                    {
                        _loggingService.Debug($"Successfully ingested content entity ({id})");
                    }
                }
            }
            catch (Exception exception)
            {
                Debug.WriteLine(exception.ToString());
            }
        }