/// <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>
        /// Allows to write the task status
        /// </summary>
        /// <param name="status">The status to write</param>
        /// <param name="token">The cancellation token, if any</param>
        /// <returns></returns>
        public Task WriteTaskStatusAsync(TransformationProcessTaskStatus status, CancellationToken token = default)
        {
            if (status == null) throw new ArgumentNullException(nameof(status));

            taskStatuses.AddOrUpdate(status.Id, status, (k, o) => status);
            return Task.CompletedTask;
        }
        /// <summary>
        /// Raises the task progress, if a TaskProgress function is defined
        /// </summary>
        /// <param name="status">The status to notify</param>
        protected virtual Task RaiseTasksProgressAsync(TransformationProcessTaskStatus status)
        {
            if (TasksProgress != null)
            {
                return(TasksProgress(status));
            }

            return(Task.CompletedTask);
        }
        /// <summary>
        /// Sets the status of a task
        /// </summary>
        /// <param name="status">The process task status</param>
        /// <param name="token">Cancellation token to use, if any</param>
        protected virtual async Task ChangeTaskStatusAsync(TransformationProcessTaskStatus status, CancellationToken token)
        {
            if (status == null)
            {
                throw new ArgumentNullException(nameof(status));
            }

            // Save the new state
            await TransformationStateManager
            .WriteTaskStatusAsync(status, token)
            .ConfigureAwait(false);

            await RaiseTasksProgressAsync(status).ConfigureAwait(false);
        }
Exemplo n.º 5
0
        private async Task Run(ISourceProvider sourceProvider, PnPContext targetContext, CancellationToken token)
        {
            try
            {
                // Iterate through each task
                await foreach (var task in transformationDistiller.GetPageTransformationTasksAsync(sourceProvider, targetContext, token))
                {
                    var taskStatus = TransformationProcessTaskStatus.CreateNormal(Id, task.Id, DateTimeOffset.Now, DateTimeOffset.Now, null, TransformationTaskExecutionState.Running);
                    try
                    {
                        // Save the task status to pending
                        await ChangeTaskStatusAsync(taskStatus).ConfigureAwait(false);

                        // Execute the actual transformation task
                        await pageTransformator.TransformAsync(task, token).ConfigureAwait(false);

                        // Save the task status to completed
                        taskStatus = TransformationProcessTaskStatus.CreateNormal(Id, task.Id, taskStatus.CreationDate, taskStatus.StartDate, DateTimeOffset.Now, TransformationTaskExecutionState.Completed);
                        await ChangeTaskStatusAsync(taskStatus).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        logger.LogError(ex, "Error while transforming task {id}", task.Id);

                        // Save the task status to faulted
                        taskStatus = TransformationProcessTaskStatus.CreateFaulted(Id, task.Id, taskStatus.CreationDate, taskStatus.StartDate, DateTimeOffset.Now, ex);
                        await ChangeTaskStatusAsync(taskStatus).ConfigureAwait(false);
                    }
                }

                // Mark the process as completed
                await ChangeProcessStateAsync(TransformationExecutionState.Completed).ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                // Mark the process as aborted and ignore this kind of error
                await ChangeProcessStateAsync(TransformationExecutionState.Aborted).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "The entire process has failed");
                // Mark the process as faulted
                await ChangeProcessStateAsync(TransformationExecutionState.Faulted).ConfigureAwait(false);
            }
        }
        /// <summary>
        /// Starts the Transformation Process
        /// </summary>
        public override async Task StartProcessAsync(ISourceProvider sourceProvider, PnPContext targetContext, CancellationToken token = default)
        {
            // Check if process is already running
            var status = await GetStatusAsync(token).ConfigureAwait(false);

            if (status.State != TransformationExecutionState.Pending)
            {
                throw new InvalidOperationException("Process cannot be started twice!");
            }

            var transformationDistiller = ServiceProvider.GetRequiredService <ITransformationDistiller>();

            // Change state to running
            await ChangeProcessStatusAsync(TransformationExecutionState.Running, token).ConfigureAwait(false);

            try
            {
                await foreach (var task in transformationDistiller.GetPageTransformationTasksAsync(sourceProvider, targetContext, token).WithCancellation(token))
                {
                    // Mark task as pending
                    await ChangeTaskStatusAsync(TransformationProcessTaskStatus.CreatePending(Id, task.Id, DateTimeOffset.Now), token)
                    .ConfigureAwait(false);

                    // Queue item
                    await EnqueueTaskAsync(task, token).ConfigureAwait(false);
                }
            }
            catch (OperationCanceledException)
            {
                // Change state to aborted
                await ChangeProcessStatusAsync(TransformationExecutionState.Aborted, token).ConfigureAwait(false);

                throw;
            }
            catch (Exception)
            {
                // Change state to faulted
                await ChangeProcessStatusAsync(TransformationExecutionState.Faulted, token).ConfigureAwait(false);

                throw;
            }
        }
Exemplo n.º 7
0
        private Task ChangeTaskStatusAsync(TransformationProcessTaskStatus status)
        {
            tasksStatuses[status.Id] = status;

            return(RaiseTasksProgressAsync(status));
        }