<PackageReference Include="Relativity.Transfer.Client" Version="6.3.7" />

WorkspaceService

using Polly; using Relativity.Transfer.Dto; using Relativity.Transfer.Resources; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; namespace Relativity.Transfer { public class WorkspaceService : RestServiceBase, IWorkspaceService { public WorkspaceService(RelativityConnectionInfo connectionInfo, ITransferLog log) : base(connectionInfo, log) { } public WorkspaceService(RelativityConnectionInfo connectionInfo, ITransferLog log, int maxRetryAttempts, double timeoutSeconds) : base(connectionInfo, log, maxRetryAttempts, timeoutSeconds) { } public Task<IEnumerable<Workspace>> GetAllWorkspacesAsync() { return GetAllWorkspacesAsync(false); } public Task<IEnumerable<Workspace>> GetAllWorkspacesAsync(bool details) { return GetAllWorkspacesAsync(details, CancellationToken.None); } public Task<IEnumerable<Workspace>> GetAllWorkspacesAsync(CancellationToken token) { return GetAllWorkspacesAsync(false, token); } public Task<IEnumerable<Workspace>> GetAllWorkspacesAsync(bool details, CancellationToken token) { return GetAllWorkspacesAsync(null, details, token); } public Task<IEnumerable<Workspace>> GetAllWorkspacesAsync(string condition, CancellationToken token) { return GetAllWorkspacesAsync(condition, false, token); } public async Task<IEnumerable<Workspace>> GetAllWorkspacesAsync(string condition, bool details, CancellationToken token) { RestClient restClient = new RestClient(new HttpConnectionInfo(ConnectionInfo), Log, TimeoutSeconds, MaxRetryAttempts); if (string.IsNullOrEmpty(condition)) condition = "\"\""; else QueryDto.NormalizeCondition(ref condition); Log.LogDebug("Preparing to retrieve all workspaces that match the '{Condition}' query condition from the '{Host}' Relativity server.", condition, ConnectionInfo.Host); string content = $"""{condition}"""; <>c__DisplayClass7_0 <>c__DisplayClass7_; QueryResultSlimDto response2 = <>c__DisplayClass7_.response; QueryResultSlimDto response; QueryResultSlimDto queryResultSlimDto = response = await restClient.RequestPostAsync<QueryResultSlimDto>("Relativity.Rest/API/Relativity.Objects/workspace/-1/object/queryslim", content, (int retryAttempt) => TimeSpan.FromSeconds(Math.Pow(2, (double)retryAttempt)), delegate(Exception exception, TimeSpan timespan, Context context) { base.Log.LogError(exception, "Retry - {Timespan} - Failed to retrieve all workspace information using the '{Condition} condition from the '{Host}' Relativity server.", timespan, condition, base.ConnectionInfo.Host); }, (HttpStatusCode code) => "query workspaces by condition", (HttpStatusCode code) => string.Format(CultureInfo.CurrentCulture, CoreStrings.WorkspaceConditionHttpGetExceptionMessage, base.ConnectionInfo.Host), token).ConfigureAwait(false); bool cloudInstance = await GetIsRelativityOneInstanceAsync(token).ConfigureAwait(false); List<Workspace> workspaces = response.Objects.AsParallel().Select(delegate(RelativityObjectSlimDto dto) { WorkspaceDto dto2 = QueryResultSlimDtoTransformer.Transform<WorkspaceDto>(dto, response.Fields); return CreateWorkspace(dto2); }).ToList(); List<Workspace>.Enumerator enumerator = workspaces.GetEnumerator(); try { while (enumerator.MoveNext()) { await RetrieveDetailsAsync(enumerator.Current, cloudInstance, details, token).ConfigureAwait(false); } } finally { ((IDisposable)enumerator).Dispose(); } enumerator = default(List<Workspace>.Enumerator); Log.LogDebug("Successfully retrieved {WorkspaceCount} workspaces that matched the '{Condition}' query condition from the '{Host}' Relativity server.", workspaces.Count, condition, ConnectionInfo.Host); return workspaces; } public Task<Workspace> GetWorkspaceAsync() { return GetWorkspaceAsync(CancellationToken.None); } public Task<Workspace> GetWorkspaceAsync(CancellationToken token) { return GetWorkspaceAsync(base.ConnectionInfo.WorkspaceId, token); } public Task<Workspace> GetWorkspaceAsync(int workspaceArtifactId) { return GetWorkspaceAsync(workspaceArtifactId, CancellationToken.None); } public async Task<Workspace> GetWorkspaceAsync(int workspaceArtifactId, CancellationToken token) { if (workspaceArtifactId == -1) return Workspace.AdminWorkspace; if (workspaceArtifactId < 1) { string message = string.Format(CultureInfo.CurrentCulture, CoreStrings.ArtifactOutOfRangeExceptionMessage, "Workspace"); throw new ArgumentOutOfRangeException("workspaceArtifactId", message); } Log.LogDebug("Preparing to retrieve the '{WorkspaceArtifactId}' workspace from the '{Host}' Relativity server.", workspaceArtifactId, ConnectionInfo.Host); RestClient restClient = new RestClient(new HttpConnectionInfo(ConnectionInfo), Log, TimeoutSeconds, MaxRetryAttempts); string content = $"""{workspaceArtifactId}"""; QueryResultSlimDto queryResultSlimDto = await restClient.RequestPostAsync<QueryResultSlimDto>("Relativity.Rest/API/Relativity.Objects/workspace/-1/object/queryslim", content, (int retryAttempt) => TimeSpan.FromSeconds(Math.Pow(2, (double)retryAttempt)), delegate(Exception exception, TimeSpan timespan, Context context) { base.Log.LogError(exception, "Retry - {Timespan} - Failed to retrieve the '{WorkspaceArtifactId}' workspace from the '{Host}' Relativity server.", timespan, workspaceArtifactId, base.ConnectionInfo.Host); }, (HttpStatusCode code) => "query single workspace", (HttpStatusCode code) => string.Format(CultureInfo.CurrentCulture, CoreStrings.WorkspaceHttpGetExceptionMessage, workspaceArtifactId, base.ConnectionInfo.Host), token).ConfigureAwait(false); WorkspaceDto dto; try { if (!queryResultSlimDto.Objects.Any()) { Log.LogWarning("Successfully retrieved the '{WorkspaceArtifactId}' workspace from the '{Host}' Relativity server but it does not exist.", workspaceArtifactId, ConnectionInfo.Host); return null; } dto = QueryResultSlimDtoTransformer.Transform<WorkspaceDto>(queryResultSlimDto.Objects[0], queryResultSlimDto.Fields); } catch (Exception exception2) { Log.LogError(exception2, "Successfully retrieved the '{WorkspaceArtifactId}' workspace from the '{Host}' Relativity but Deserialization failed", workspaceArtifactId, ConnectionInfo.Host); return null; } bool cloudInstance = await GetIsRelativityOneInstanceAsync(token).ConfigureAwait(false); Workspace workspace = CreateWorkspace(dto); if (string.IsNullOrEmpty(workspace.DefaultFileShareUncPath)) throw new TransferException(string.Format(CultureInfo.CurrentCulture, CoreStrings.WorkspaceNoDefaultFileShareUncPathExceptionMessage, workspaceArtifactId), true); Log.LogDebug("Successfully retrieved the '{WorkspaceArtifactId}-{WorkspaceName}' workspace from the '{Host}' Relativity server.", workspaceArtifactId, workspace.Name, ConnectionInfo.Host); await RetrieveDetailsAsync(workspace, cloudInstance, true, token).ConfigureAwait(false); return workspace; } public Task<IEnumerable<FileShareResourceServer>> GetFileShareResourceServersAsync() { return GetFileShareResourceServersAsync(base.ConnectionInfo.WorkspaceId); } public Task<IEnumerable<FileShareResourceServer>> GetFileShareResourceServersAsync(CancellationToken token) { return GetFileShareResourceServersAsync(base.ConnectionInfo.WorkspaceId, token); } public Task<IEnumerable<FileShareResourceServer>> GetFileShareResourceServersAsync(int workspaceArtifactId) { return GetFileShareResourceServersAsync(workspaceArtifactId, CancellationToken.None); } public async Task<IEnumerable<FileShareResourceServer>> GetFileShareResourceServersAsync(int workspaceArtifactId, CancellationToken token) { if (workspaceArtifactId < 1) { string message = string.Format(CultureInfo.CurrentCulture, CoreStrings.ArtifactOutOfRangeExceptionMessage, "Workspace"); throw new ArgumentOutOfRangeException("workspaceArtifactId", message); } Log.LogDebug("Preparing to retrieve the resource servers within the '{WorkspaceArtifactId}' workspace from the '{Host}' Relativity server.", workspaceArtifactId, ConnectionInfo.Host); RestClient restClient = new RestClient(new HttpConnectionInfo(ConnectionInfo), Log, TimeoutSeconds, MaxRetryAttempts); string content = SerializationHelper.SerializeToJson(new { workspace = new { Guids = (object[])null, ArtifactID = workspaceArtifactId, Name = (string)null } }); List<FileShareResourceServerDto> response = await restClient.RequestPostAsync<List<FileShareResourceServerDto>>("/relativity.rest/api/Relativity.Services.Workspace.IWorkspaceModule/Workspace%20Manager%20Service/GetAssociatedFileShareResourceServersAsync", content, (int retryAttempt) => TimeSpan.FromSeconds(Math.Pow(2, (double)retryAttempt)), delegate(Exception exception, TimeSpan timespan, Context context) { base.Log.LogError(exception, "Retry - {Timespan} - Failed to retrieve the file share resource servers within the '{WorkspaceArtifactId}' workspace from the '{Host}' Relativity server.", timespan, workspaceArtifactId, base.ConnectionInfo.Host); }, (HttpStatusCode code) => "query file share resource servers by workspace", (HttpStatusCode code) => string.Format(CultureInfo.CurrentCulture, CoreStrings.WorkspaceFileShareResourceServersHttpGetExceptionMessage, workspaceArtifactId, base.ConnectionInfo.Host), token).ConfigureAwait(false); <>c__DisplayClass15_0 <>c__DisplayClass15_; bool cloudInstance2 = <>c__DisplayClass15_.cloudInstance; bool cloudInstance = await GetIsRelativityOneInstanceAsync(token).ConfigureAwait(false); List<FileShareResourceServer> fileShareResourceServers = response.Select(delegate(FileShareResourceServerDto dto) { dto.UncPath = base.FileSystemService.TrimTrailingSlash(dto.UncPath); return ResourceServerService.CreateFileShareResourceServer(dto, cloudInstance); }).ToList(); Log.LogDebug("Successfully retrieved {ResourceServerCount} file share resource servers within the '{WorkspaceArtifactId}' workspace from the '{Host}' Relativity server.", fileShareResourceServers.Count, workspaceArtifactId, ConnectionInfo.Host); ICredentialService credentialService = ServiceFactory.CreateCredentialService(); List<FileShareResourceServer>.Enumerator enumerator = fileShareResourceServers.GetEnumerator(); try { while (enumerator.MoveNext()) { FileShareResourceServer current = enumerator.Current; if (current.ResourceServerType == null) current.ResourceServerType = new ResourceServerType(); current.ResourceServerType.Name = "Fileshare"; FileShareResourceServer fileShareResourceServer = current; fileShareResourceServer.AsperaCredentials = await credentialService.GetResourceServerAsperaCredentialsAsync(current.ArtifactId, token).ConfigureAwait(false); } } finally { ((IDisposable)enumerator).Dispose(); } enumerator = default(List<FileShareResourceServer>.Enumerator); return fileShareResourceServers; } public Task<IEnumerable<SqlResourceServer>> GetSqlResourceServersAsync() { return GetSqlResourceServersAsync(base.ConnectionInfo.WorkspaceId); } public Task<IEnumerable<SqlResourceServer>> GetSqlResourceServersAsync(CancellationToken token) { return GetSqlResourceServersAsync(base.ConnectionInfo.WorkspaceId, token); } public Task<IEnumerable<SqlResourceServer>> GetSqlResourceServersAsync(int workspaceArtifactId) { return GetSqlResourceServersAsync(workspaceArtifactId, CancellationToken.None); } public async Task<IEnumerable<SqlResourceServer>> GetSqlResourceServersAsync(int workspaceArtifactId, CancellationToken token) { if (workspaceArtifactId < 1) { string message = string.Format(CultureInfo.CurrentCulture, CoreStrings.ArtifactOutOfRangeExceptionMessage, "Workspace"); throw new ArgumentOutOfRangeException("workspaceArtifactId", message); } Log.LogDebug("Preparing to retrieve the SQL resource servers within the '{WorkspaceArtifactId}' workspace from the '{Host}' Relativity server.", workspaceArtifactId, ConnectionInfo.Host); RestClient restClient = new RestClient(new HttpConnectionInfo(ConnectionInfo), Log, TimeoutSeconds, MaxRetryAttempts); string content = SerializationHelper.SerializeToJson(new { workspace = new { Guids = (object[])null, ArtifactID = workspaceArtifactId, Name = (string)null } }); List<SqlResourceServerDto> response = await restClient.RequestPostAsync<List<SqlResourceServerDto>>("/relativity.rest/api/Relativity.Services.Workspace.IWorkspaceModule/Workspace%20Manager%20Service/GetAssociatedSQLServersAsync", content, (int retryAttempt) => TimeSpan.FromSeconds(Math.Pow(2, (double)retryAttempt)), delegate(Exception exception, TimeSpan timespan, Context context) { base.Log.LogError(exception, "Retry - {Timespan} - Failed to retrieve the SQL resource servers within the '{WorkspaceArtifactId}' workspace from the '{Host}' Relativity server.", timespan, workspaceArtifactId, base.ConnectionInfo.Host); }, (HttpStatusCode code) => "query SQL resource servers by workspace", (HttpStatusCode code) => string.Format(CultureInfo.CurrentCulture, CoreStrings.WorkspaceSqlResourceServersHttpGetExceptionMessage, workspaceArtifactId, base.ConnectionInfo.Host), token).ConfigureAwait(false); <>c__DisplayClass19_0 <>c__DisplayClass19_; bool cloudInstance2 = <>c__DisplayClass19_.cloudInstance; bool cloudInstance = await GetIsRelativityOneInstanceAsync(token).ConfigureAwait(false); List<SqlResourceServer> sqlResourceServers = (from x in response select CreateSqlResourceServer(x, cloudInstance)).ToList(); Log.LogDebug("Successfully retrieved {SqlResourceServerCount} SQL resource servers within the '{WorkspaceArtifactId}' workspace from the '{Host}' Relativity server.", sqlResourceServers.Count, workspaceArtifactId, ConnectionInfo.Host); ICredentialService credentialService = ServiceFactory.CreateCredentialService(); List<SqlResourceServer>.Enumerator enumerator = sqlResourceServers.GetEnumerator(); try { while (enumerator.MoveNext()) { SqlResourceServer current = enumerator.Current; if (current.ResourceServerType == null) current.ResourceServerType = new ResourceServerType(); if (string.Compare(current.ResourceServerType.Name, "SqlPrimary", StringComparison.OrdinalIgnoreCase) == 0) current.ResourceServerType.Name = "SQL - Primary"; else if (string.Compare(current.ResourceServerType.Name, "SqlDistributed", StringComparison.OrdinalIgnoreCase) == 0) { current.ResourceServerType.Name = "SQL - Distributed"; } SqlResourceServer sqlResourceServer = current; sqlResourceServer.AsperaCredentials = await credentialService.GetResourceServerAsperaCredentialsAsync(current.ArtifactId, token).ConfigureAwait(false); } } finally { ((IDisposable)enumerator).Dispose(); } enumerator = default(List<SqlResourceServer>.Enumerator); return sqlResourceServers; } private SqlResourceServer CreateSqlResourceServer(SqlResourceServerDto dto, bool cloudInstance) { return new SqlResourceServer { ArtifactId = dto.ArtifactId, BcpPath = base.FileSystemService.TrimTrailingSlash(dto.BcpPath), CloudInstance = cloudInstance, Name = dto.Name, ResourceServerType = new ResourceServerType { ArtifactId = dto.ServerType.ArtifactId, Name = dto.ServerType.Name }, Version = dto.Version }; } private Workspace CreateWorkspace(WorkspaceDto dto) { return new Workspace { ArtifactId = dto.ArtifactId, DefaultFileShareUncPath = base.FileSystemService.TrimTrailingSlash(dto.DefaultFileLocation), DownloadHandlerUrl = dto.DownloadHandlerUrl, Name = dto.Name }; } private async Task<List<Guid>> RetrieveWorkspaceGuidAsync(int workspaceArtifactId, CancellationToken token) { if (workspaceArtifactId < 1) { string message = string.Format(CultureInfo.CurrentCulture, CoreStrings.ArtifactOutOfRangeExceptionMessage, "Workspace"); throw new ArgumentOutOfRangeException("workspaceArtifactId", message); } Log.LogDebug("Preparing to retrieve the Workspace Guid of workspace: '{WorkspaceArtifactId}' from the '{Host}' Relativity server.", workspaceArtifactId, ConnectionInfo.Host); RestClient restClient = new RestClient(new HttpConnectionInfo(ConnectionInfo), Log, TimeoutSeconds, MaxRetryAttempts); string content = SerializationHelper.SerializeToJson(new { workspaceId = -1, artifactId = workspaceArtifactId }); List<Guid> list = await restClient.RequestPostAsync<List<Guid>>("relativity.rest/api/Relativity.Services.ArtifactGuid.IArtifactGuidModule/Artifact Guid Manager/ReadSingleGuidsAsync", content, (int retryAttempt) => TimeSpan.FromSeconds(Math.Pow(2, (double)retryAttempt)), delegate(Exception exception, TimeSpan timespan, Context context) { base.Log.LogError(exception, "Retry - {Timespan} - Failed to retrieve the Workspace Guid of workspace: '{WorkspaceArtifactId}' from the '{Host}' Relativity server.", timespan, workspaceArtifactId, base.ConnectionInfo.Host); }, (HttpStatusCode code) => "query SQL resource servers by workspace", (HttpStatusCode code) => string.Format(CultureInfo.CurrentCulture, CoreStrings.WorkspaceSqlResourceServersHttpGetExceptionMessage, workspaceArtifactId, base.ConnectionInfo.Host), token).ConfigureAwait(false); Log.LogDebug("Successfully retrieved Workspace Guid of workspace: '{WorkspaceArtifactId}' from the '{Host}' Relativity server.", list.Count, workspaceArtifactId, ConnectionInfo.Host); return list; } private async Task RetrieveDetailsAsync(Workspace workspace, bool cloudInstance, bool details, CancellationToken token) { Workspace workspace2; if (details) { workspace2 = workspace; IReadOnlyList<FileShareResourceServer> readOnlyList2 = workspace2.FileShareResourceServers = (await GetFileShareResourceServersAsync(workspace.ArtifactId, token).ConfigureAwait(false)).ToList(); if (workspace.FileShareResourceServers.Count == 0) throw new TransferException(string.Format(CultureInfo.CurrentCulture, CoreStrings.WorkspaceNoFileShareResourceServersExceptionMessage, workspace.ArtifactId), true); Log.LogDebug("Successfully retrieved {Count} file share resource servers for the '{WorkspaceArtifactId}-{WorkspaceName}' workspace.", workspace.FileShareResourceServers.Count, workspace.ArtifactId, workspace.Name); FileShareResourceServer fileShareResourceServer = workspace.FileShareResourceServers.FirstOrDefault((FileShareResourceServer x) => string.Compare(x.UncPath, workspace.DefaultFileShareUncPath, StringComparison.OrdinalIgnoreCase) == 0); if (fileShareResourceServer == null) throw new TransferException(string.Format(CultureInfo.CurrentCulture, CoreStrings.WorkspaceNoDefaultFileShareExceptionMessage, workspace.ArtifactId, workspace.FileShareResourceServers.Count, workspace.DefaultFileShareUncPath), false); Log.LogDebug("Successfully retrieved the '{DefaultFileShareResourceServerName}' default file share resource server for the '{WorkspaceArtifactId}-{WorkspaceName}' workspace.", fileShareResourceServer.Name, workspace.ArtifactId, workspace.Name); workspace.DefaultFileShare = new RelativityFileShare(fileShareResourceServer); workspace2 = workspace; workspace2.SqlResourceServers = (await GetSqlResourceServersAsync(workspace.ArtifactId, token).ConfigureAwait(false)).ToList(); if ((workspace.SqlResourceServers.Count == 0) & cloudInstance) throw new TransferException(string.Format(CultureInfo.CurrentCulture, CoreStrings.WorkspaceNoSqlServerResourceServersExceptionMessage, workspace.ArtifactId), true); Log.LogDebug("Successfully retrieved {Count} SQL resource servers for the '{WorkspaceArtifactId}-{WorkspaceName}' workspace.", workspace.SqlResourceServers.Count, workspace.ArtifactId, workspace.Name); workspace.PrimarySqlResourceServer = workspace.SqlResourceServers.FirstOrDefault((SqlResourceServer x) => ResourceServerType.IsSqlPrimaryMatch(x.ResourceServerType)); if (workspace.PrimarySqlResourceServer != null) Log.LogDebug("Successfully retrieved the '{PrimarySqlResourceServerName}' primary SQL resource server for the '{WorkspaceArtifactId}-{WorkspaceName}' workspace.", workspace.PrimarySqlResourceServer.Name, workspace.ArtifactId, workspace.Name); workspace.DistributedSqlResourceServer = workspace.SqlResourceServers.FirstOrDefault((SqlResourceServer x) => ResourceServerType.IsSqlDistributedMatch(x.ResourceServerType)); if (workspace.DistributedSqlResourceServer != null) Log.LogDebug("Successfully retrieved the '{DistributedSqlResourceServerName}' distributed SQL resource server for the '{WorkspaceArtifactId}-{WorkspaceName}' workspace.", workspace.DistributedSqlResourceServer.Name, workspace.ArtifactId, workspace.Name); } workspace2 = workspace; workspace2.Guids = await RetrieveWorkspaceGuidAsync(workspace.ArtifactId, token).ConfigureAwait(false); } } }