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>> ()
{
return GetFileShareResourceServersAsync(base.ConnectionInfo.WorkspaceId);
}
public Task<IEnumerable<FileShareResourceServer>> (CancellationToken token)
{
return GetFileShareResourceServersAsync(base.ConnectionInfo.WorkspaceId, token);
}
public Task<IEnumerable<FileShareResourceServer>> (int workspaceArtifactId)
{
return GetFileShareResourceServersAsync(workspaceArtifactId, CancellationToken.None);
}
public async Task<IEnumerable<FileShareResourceServer>> (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);
}
}
}