/// <summary> /// Process a task and update the status /// </summary> /// <param name="task">The task item to process</param> /// <param name="token">The cancellation token, if any</param> /// <returns></returns> public virtual async Task <TransformationProcessTaskStatus> ProcessTaskAsync(PageTransformationTask task, CancellationToken token = default) { if (task == null) { throw new ArgumentNullException(nameof(task)); } var logger = ServiceProvider.GetRequiredService <ILogger <LongRunningTransformationProcessBase> >(); var pageTransformator = ServiceProvider.GetRequiredService <IPageTransformator>(); // Retrieve the status for the task var taskStatus = await GetTaskStatusAsync(task.Id, token).ConfigureAwait(false); // Check if task has been already processed if (taskStatus.State != TransformationTaskExecutionState.Pending) { // Skip return(taskStatus); } // Retrieve current process status var status = await GetStatusAsync(token).ConfigureAwait(false); // Process is not running, skip the task if (status.State != TransformationExecutionState.Running) { // Mark task as aborted taskStatus = TransformationProcessTaskStatus.CreateNormal(Id, task.Id, taskStatus.CreationDate, taskStatus.StartDate, DateTimeOffset.Now, TransformationTaskExecutionState.Aborted); await ChangeTaskStatusAsync(taskStatus, token).ConfigureAwait(false); return(taskStatus); } try { // Mark task as running taskStatus = TransformationProcessTaskStatus.CreateNormal(Id, task.Id, taskStatus.CreationDate, DateTimeOffset.Now, null, TransformationTaskExecutionState.Running); await ChangeTaskStatusAsync(taskStatus, token).ConfigureAwait(false); // Run the actual transformation task await pageTransformator.TransformAsync(task, token).ConfigureAwait(false); // Mark task as completed taskStatus = TransformationProcessTaskStatus.CreateNormal(Id, task.Id, taskStatus.CreationDate, taskStatus.StartDate, DateTimeOffset.Now, TransformationTaskExecutionState.Completed); await ChangeTaskStatusAsync(taskStatus, token).ConfigureAwait(false); return(taskStatus); } catch (Exception ex) { logger.LogError(ex, "Error while transforming task {id}", task.Id); // Mark task as faulted taskStatus = TransformationProcessTaskStatus.CreateFaulted(Id, task.Id, taskStatus.CreationDate, taskStatus.StartDate, DateTimeOffset.Now, ex); await ChangeTaskStatusAsync(taskStatus, token).ConfigureAwait(false); return(taskStatus); } }
/// <summary> /// Adds the task to a queue in order to process it asynchronously /// </summary> /// <param name="task">The task item to enqueue</param> /// <param name="token">The cancellation token, if any</param> protected abstract Task EnqueueTaskAsync(PageTransformationTask task, CancellationToken token);
/// <summary> /// Transforms a page from the configured data source to a modern SharePoint Online page /// </summary> /// <param name="task">The context of the transformation process</param> /// <param name="token">The cancellation token, if any</param> /// <returns>The URL of the transformed page</returns> public virtual async Task <Uri> TransformAsync(PageTransformationTask task, CancellationToken token = default) { if (task == null) { throw new ArgumentNullException(nameof(task)); } logger.LogInformation( TransformationResources.Info_RunningTransformationTask.CorrelateString(task.Id), task.Id, task.SourceItemId.Id); // Get the source item by id var sourceItem = await task.SourceProvider.GetItemAsync(task.SourceItemId, token).ConfigureAwait(false); // Resolve the target page uri var targetPageUri = await targetPageUriResolver.ResolveAsync(sourceItem, task.TargetContext, token).ConfigureAwait(false); // Call pre transformations handlers var preContext = new PagePreTransformationContext(task, sourceItem, targetPageUri); foreach (var pagePreTransformation in pagePreTransformations) { await pagePreTransformation.PreTransformAsync(preContext, token).ConfigureAwait(false); token.ThrowIfCancellationRequested(); } // Save start date and time for telemetry DateTime transformationStartDateTime = DateTime.Now; // Invoke the configured main mapping provider var context = new PageTransformationContext(task, sourceItem, targetPageUri); var input = new MappingProviderInput(context); MappingProviderOutput output = await mappingProvider.MapAsync(input, token).ConfigureAwait(false); token.ThrowIfCancellationRequested(); // Here we generate the actual SPO modern page in SharePoint Online var generatedPage = await pageGenerator.GenerateAsync(context, output, targetPageUri, token).ConfigureAwait(false); var generatedPageUri = generatedPage.GeneratedPageUrl; token.ThrowIfCancellationRequested(); // Save duration for telemetry TimeSpan duration = DateTime.Now.Subtract(transformationStartDateTime); // Save telemetry var telemetryProperties = output.TelemetryProperties.Merge(generatedPage.TelemetryProperties); // Add global telemetry properties telemetryProperties.Add(TelemetryService.CorrelationId, task.Id.ToString()); telemetryProperties.Add(TelemetryService.AADTenantId, context.Task.TargetContext.GlobalOptions.AADTenantId.ToString()); this.telemetry.LogTransformationCompleted(duration, telemetryProperties); // Call post transformations handlers var postContext = new PagePostTransformationContext(task, sourceItem, generatedPageUri); foreach (var pagePostTransformation in pagePostTransformations) { await pagePostTransformation.PostTransformAsync(postContext, token).ConfigureAwait(false); token.ThrowIfCancellationRequested(); } return(generatedPageUri); }
/// <summary> /// Creates an instance of PagePostTransformationContext /// </summary> /// <param name="task">The page transformation task</param> /// <param name="sourceItem">The source item of the transformation</param> /// <param name="targetPageUri">The target URI of the transformed page</param> public PagePostTransformationContext(PageTransformationTask task, ISourceItem sourceItem, Uri targetPageUri) : base(task, sourceItem, targetPageUri) { }
/// <summary> /// Creates an instance of PageTransformationContext /// </summary> /// <param name="task">The page transformation task</param> /// <param name="sourceItem">The source item of the transformation</param> /// <param name="targetPageUri">The target URI of the transformed page</param> public PageTransformationContext(PageTransformationTask task, ISourceItem sourceItem, Uri targetPageUri) { Task = task ?? throw new ArgumentNullException(nameof(task)); SourceItem = sourceItem ?? throw new ArgumentNullException(nameof(sourceItem)); TargetPageUri = targetPageUri ?? throw new ArgumentNullException(nameof(targetPageUri)); }