Example #1
0
        // TODO TransactionScope?
        /// <summary>
        ///     Processes a single Ableton project folder by syncing its metadata
        ///     to our data store. If the state is considered invalid, this is
        ///     marked both in our data store and in our tracking file.
        /// </summary>
        /// <remarks>
        ///     This does nothing with project tasks.
        ///
        ///     If the given <paramref name="directoryInfo"/> is not an Ableton
        ///     project directory, this will throw an exception of type
        ///     <see cref="NotAnAbletonProjectFolderException"/>.
        ///
        ///     Note: This service does not consider the possibility of a project
        ///     existing in the data store without it having a tracking file.
        /// </remarks>
        /// <param name="directoryInfo">The directory to process.</param>
        /// <param name="token">The cancellation token.</param>
        /// <returns>See <see cref="Task"/>.</returns>
        public async Task ProcessAbletonProjectFolderAsync(DirectoryInfo directoryInfo, CancellationToken token)
        {
            if (directoryInfo == null)
            {
                throw new ArgumentNullException(nameof(directoryInfo));
            }
            if (token == null)
            {
                throw new ArgumentNullException(nameof(token));
            }

            try
            {
                if (!ProjectFolderHelper.IsAbletonProjectFolder(directoryInfo))
                {
                    throw new NotAnAbletonProjectFolderException();
                }

                if (_trackingFileService.HasTrackingFile(directoryInfo))
                {
                    // If marked invalid, this service will log and skip.
                    var trackingFile = _trackingFileService.GetTrackingFile(directoryInfo);
                    if (trackingFile.TrackingFileStatus == TrackingFileStatus.InvalidLocal)
                    {
                        _logger.LogWarning($"Project with id {trackingFile.ProjectId} marked as invalid, skipping");
                        return;
                    }

                    if (!await _projectRepository.ExistsAsync(trackingFile.ProjectId, token))
                    {
                        // If the project has a tracking file but does not exist in the store,
                        // we have reached an invalid state. This should never happen.
                        _trackingFileService.MarkTrackingFileInvalidLocal(directoryInfo);
                        _logger.LogWarning($"Project with id {trackingFile.ProjectId} has a tracking file" +
                                           $"but does not exist in the store - marked as invalid.");
                        return;
                    }
                    else
                    {
                        // The state where there exists a tracking file and where the project
                        // exists in the data store is valid. We can continue to process.
                        // TODO Transaction?
                        var project = await _projectRepository.GetAsync(trackingFile.ProjectId, token);

                        project = await _projectRepository.MarkProjectAsScrapedAsync(trackingFile.ProjectId, token);

                        _trackingFileService.MarkProjectScraped(directoryInfo);

                        _logger.LogTrace($"Project with id {trackingFile.ProjectId} has been scraped");
                        return;
                    }
                }
                else
                {
                    // If no tracking file exists we can only assume that the project is
                    // not yet being tracked. This will start tracking the project.
                    var extractedProject = ProjectFolderHelper.ExtractProject(directoryInfo);

                    // TODO This should not happen here.
                    var root = _options.RootDirectoryPath.LocalPath;
                    extractedProject.RelativePath = PathHelper.GetRelativePath(directoryInfo.FullName, root);

                    // TODO Transaction?
                    var createdProjectId = await _projectRepository.CreateAsync(extractedProject, token);

                    _trackingFileService.CreateTrackingFile(createdProjectId, directoryInfo);
                    _logger.LogTrace($"A new tracking file has been created for project {createdProjectId} at {directoryInfo.FullName}");

                    return;
                }
            }
            catch (IOException e)
            {
                _logger.LogError(e.Message);
                throw new FileAccessException("Could not determine if directory was Ableton project", e);
            }
        }