using System; using System.Collections.Generic; using System.IO; using System.IO.Abstractions; using System.Linq; using System.Threading.Tasks; using BO.AppServer.Metadata.Dto; using BO.AppServer.Metadata.Enums; using BO.ProcessServer.Options; using Connector.PS; using Quadarax.Foundation.Core.IO.MimeTypes; using Quadarax.Foundation.Core.Object; using Quadarax.Foundation.Core.Value.Extensions; namespace BO.ProcessServer.Business { internal class ConnectionProxy : DisposableObject, IConnectionPS { #region *** Private fields *** private Configuration _configuration; private Random _rand; private IList _documentsCache; private IFileSystem _fileSystem; private long _currentDocId; private long _currentArtId; #endregion #region *** Properties *** public bool IsOpen { get; private set; } #endregion #region *** Constructor *** public ConnectionProxy(Configuration configuration, IFileSystem fileSystem) { _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); _rand = new Random(); _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); _documentsCache = new List(); _currentDocId = _rand.Next(1, 1000); _currentArtId = _rand.Next(1, 10) * _currentDocId; } #endregion #region *** Public Operations *** public async Task> GetDocumentsAsync(DocumentsScopeEnums scope) { if (!(scope == DocumentsScopeEnums.Pending || scope == DocumentsScopeEnums.Working)) throw new ArgumentOutOfRangeException( $"Document list scope value must be '{DocumentsScopeEnums.Working}' or '{DocumentsScopeEnums.Pending}' int this context."); if (_documentsCache.Count(x=>x.Status == DocumentStatusEnum.New) + _configuration.System.Proxy.App.DefaultDocumentsCount < _configuration.System.Proxy.App.MaxDocumentsCount) GenerateDocuments(DocumentStatusEnum.New); var documents = _documentsCache.Where(x => x.Status == DocumentStatusEnum.New) .Take(_configuration.System.PoolPullDocuments).ToArray(); foreach (var document in documents) document.Status = DocumentStatusEnum.Pending; return documents; } public async Task GetDocumentStateAsync(long documentId) { return _documentsCache.Where(x => x.Id == documentId).Select(x=>x.Status).First(); } public async Task GetDocumentInfoAsync(long documentId) { return _documentsCache.First(x => x.Id == documentId); } public async Task SetDocumentStateAsync(long documentId, DocumentStatusEnum status) { if (!(status == DocumentStatusEnum.New || status == DocumentStatusEnum.Processing || status == DocumentStatusEnum.DoneOk || status == DocumentStatusEnum.DoneFail)) throw new ArgumentOutOfRangeException( $"Document status value must be '{DocumentStatusEnum.New}' or '{DocumentStatusEnum.Processing}' or '{DocumentStatusEnum.DoneOk}' or '{DocumentStatusEnum.DoneFail}' in this context."); var document = _documentsCache.First(x => x.Id == documentId); document.Status = status; return status; } public async Task GetDocumentContentAsync(long documentId, long artifactId) { var sw = new StreamWriter(new MemoryStream()); await sw.WriteLineAsync("This is a mock data"); await sw.FlushAsync(); sw.BaseStream.Seek(0, SeekOrigin.Begin); return sw.BaseStream; } public async Task SetDocumentContentAsync(long documentId, string fileName, string mimeType, bool overwriteIfExists, Stream contentStream) { var document = _documentsCache.First(x => x.Id == documentId); var artifacts = new List(document.Artifacts); _currentArtId++; var artifact = new ArtifactRDto() { Length = contentStream.Length, Type = ArtifactTypeEnum.Output, MimeType = mimeType, Extension = _fileSystem.Path.GetExtension(fileName), Id = _currentArtId }; artifacts.Add(artifact); document.Artifacts = artifacts; return artifact; } public void Open(string userName, string userPassword, string magicKey) { IsOpen = true; } public void Close() { IsOpen = false; } public bool Ping(out TimeSpan duration, out string status) { duration = TimeSpan.FromMilliseconds(_rand.Next(2000)); status = "OK"; return true; } #endregion #region *** Private Operations & Overrides *** protected override void OnDisposing() { _configuration = null; } protected void GenerateDocuments(DocumentStatusEnum state) { for (int a = 0; a < _configuration.System.Proxy.App.DefaultDocumentsCount; a++) { var artifacts = new List(); for (int i = 0; i < _configuration.System.Proxy.App.DefaultArtifactCount; i++) { var ext = _configuration.System.Proxy.App.Extension.GetRandom(); var artifact = new ArtifactRDto() { Id = _currentArtId++, Name = $"{_configuration.System.Proxy.App.NameProfix.GetRandom()}_{_currentArtId:D8}", Extension = ext, MimeType = MimeTypeUtil.GetMimeType(ext), Type = ArtifactTypeEnum.Input }; artifacts.Add(artifact); } var document = new DocumentRDto() { Name = $"Doc{_currentDocId++:D8}", Id = _currentDocId, PresetCreditCost = _configuration.System.Proxy.App.PresetCreditCost.GetRandom(), PresetQuality = _configuration.System.Proxy.App.PresetQuality.GetRandom(), PresetProcessProfile = _configuration.System.Proxy.App.PresetProcessProfile.GetRandom(), PresetWatermark = _configuration.System.Proxy.App.PresetWatermark.GetRandom(), PresetTest = _configuration.System.Proxy.App.PresetTest.GetRandom(), Status = state, Artifacts = artifacts }; _documentsCache.Add(document); } var toDelete = _documentsCache.Where(x => x.Status == DocumentStatusEnum.DoneFail || x.Status == DocumentStatusEnum.DoneOk || x.Status == DocumentStatusEnum.Downloaded || x.Status == DocumentStatusEnum.Expired).ToArray(); foreach (var del in toDelete) _documentsCache.Remove(del); } #endregion } }