/// <summary> /// Saves the result of the upload /// </summary> /// <param name="command">The command</param> /// <param name="cancellationToken">The cancellation token</param> /// <returns>The upload result</returns> public async Task <IUploadResult> Upload(TCommand command, CancellationToken cancellationToken) { Argument.NotNull(command, nameof(command)); var uploadResult = await _uploader .Upload(command, cancellationToken) .ConfigureAwait(Await.Default); var now = _dateTimeProvider.UtcNow; var file = _dataContext.DataSources .Where(x => string.Equals(command.Path, x.Path, StringComparison.OrdinalIgnoreCase) == true) .FirstOrDefault(); if (file == null) { file = new DataSource { Path = command.Path, Attempts = 0, }; _dataContext.DataSources.Add(file); } if (file.Attempts.HasValue == false) { file.Attempts = 0; } if (uploadResult.Success == true) { var query = new HashFileQuery { File = command.File, }; var queryResult = await _hashFileQueryHandler .Handle(query, cancellationToken) .ConfigureAwait(Await.Default); file.UploadNeeded = false; file.LastUploadDate = now; file.Size = command.Size; file.Hash = queryResult.Hash; file.CreationTimeUtc = command.CreationTimeUtc; file.LastWriteTimeUtc = command.LastWriteTimeUtc; file.LastHashCheckDate = now; file.Attempts = 1; } else { file.UploadNeeded = true; file.Attempts++; } await _dataContext .SaveChanges(cancellationToken) .ConfigureAwait(Await.Default); return(uploadResult); }
/// <summary> /// Handle the command /// </summary> /// <param name="command">The command</param> /// <param name="cancellationToken">The cancellation token</param> /// <returns>The command result</returns> public async Task <QueueIntegrationImportCommandResult> Handle( QueueIntegrationImportCommand command, CancellationToken cancellationToken) { Argument.NotNull(command, nameof(command)); var commandResult = new QueueIntegrationImportCommandResult(); if (_dataContext.IntegrationImports.TryGetValue(command.IntegrationId, out var integrationImport) == false) { integrationImport = new IntegrationImport { IntegrationId = command.IntegrationId, }; _dataContext.IntegrationImports.Add(command.IntegrationId, integrationImport); } var fileInfo = _fileInfoFactory.FromFileName(command.File); if (fileInfo.Exists) { var versionId = _guidProvider.NewGuid(); string extension = fileInfo.Extension; var now = _dateTimeProvider.UtcNow; string queueFolder = _configuration.Value.QueueFolder; string orignalFileName = fileInfo.Name; var fileDate = new DateTimeOffset(fileInfo.LastWriteTimeUtc, TimeSpan.Zero); string fileName = string.Format( CultureInfo.InvariantCulture, "{0}_{1:yyyyMMddHHmmssfff}_{2}{3}", command.IntegrationId, now, versionId, extension); var filePath = _path.Combine(queueFolder, fileName); long size = fileInfo.Length; if (command.MoveFile == true) { fileInfo.MoveTo(filePath); var queueItem = new IntegrationImportQueueItem { IntegrationId = command.IntegrationId, File = filePath, FileName = orignalFileName, FileSize = size, FileDate = fileDate, Hash = null, FileVersionId = versionId, }; _dataContext.IntegrationImportQueue.Add(queueItem); } else { using (var stream = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.Read)) { var query = new HashFileQuery { File = stream }; var queryResult = await _queryHandler .Handle(query, cancellationToken) .ConfigureAwait(Await.Default); _ = stream.Seek(0, SeekOrigin.Begin); if (string.Equals(integrationImport.Hash, queryResult.Hash, StringComparison.Ordinal) == false) { integrationImport.Hash = queryResult.Hash; integrationImport.Size = size; var writeCommand = new WriteFileFromStreamCommand { Path = queueFolder, FileName = fileName, File = stream, Size = size }; var writeCommandResult = await _commandHandler .Handle(writeCommand, cancellationToken) .ConfigureAwait(Await.Default); switch (writeCommandResult.Result) { case WriteFileFromStreamCommandResultKind.Success: break; default: throw UnexpectedEnumValueException.Create(writeCommandResult.Result); } string hash = queryResult.Hash; var queueItem = new IntegrationImportQueueItem { IntegrationId = command.IntegrationId, File = filePath, FileName = orignalFileName, FileSize = size, FileDate = fileDate, Hash = hash, FileVersionId = versionId, }; _dataContext.IntegrationImportQueue.Add(queueItem); } } } } return(commandResult); }
/// <summary> /// Handles the checking if the file needs to be uploaded /// </summary> /// <param name="query">The query</param> /// <param name="cancellationToken">The cancellation token</param> /// <returns>The response</returns> public async Task <FileNeedsUploadQueryResult> Handle( FileNeedsUploadQuery query, CancellationToken cancellationToken) { Argument.NotNull(query, nameof(query)); var queryResult = new FileNeedsUploadQueryResult(); var file = _dataContext.DataSources .Where(x => string.Equals(query.Path, x.Path, StringComparison.OrdinalIgnoreCase) == true) .FirstOrDefault(); var now = _dateTimeProvider.UtcNow; bool upload = false; var maxFileAge = _configuration.Value.MaxFileAge; var maxFileHashAge = _configuration.Value.MaxFileHashAge; if (file == null) { upload = true; } else if (file.UploadNeeded == true) { upload = true; } else if (file.Size.HasValue == false || file.Size != query.Size) { upload = true; } else if (file.CreationTimeUtc.HasValue == false || file.CreationTimeUtc != query.CreationTimeUtc) { upload = true; } else if (file.LastWriteTimeUtc.HasValue == false || file.LastWriteTimeUtc != query.LastWriteTimeUtc) { upload = true; } else if (file.LastUploadDate.HasValue == false || now - file.LastUploadDate >= maxFileAge) { upload = true; } else if (file.LastHashCheckDate.HasValue == false || string.IsNullOrEmpty(file.Hash) == true || now - file.LastHashCheckDate >= maxFileHashAge) { var hashFileQuery = new HashFileQuery { File = query.File, }; var hashFileQueryResult = await _hashFileQueryHandler .Handle(hashFileQuery, cancellationToken) .ConfigureAwait(Await.Default); if (string.Equals(file.Hash, hashFileQueryResult.Hash, StringComparison.Ordinal) == false) { upload = true; } } queryResult.FileNeedsUpload = upload; return(queryResult); }